Use xrange() rather than range() for loop iterations.
[blender.git] / source / blender / src / drawview.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) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 //#define NAN_LINEAR_PHYSICS
31
32 #include <math.h>
33 #include <string.h>
34
35 #ifndef WIN32
36 #include <unistd.h>
37 #include <sys/times.h>
38 #else
39 #include <io.h>
40 #endif   
41
42 #ifdef WIN32
43 #ifndef snprintf
44 #define snprintf _snprintf
45 #endif
46 #endif
47
48 #include "MEM_guardedalloc.h"
49
50 #include "PIL_time.h"
51
52 #include "BMF_Api.h"
53
54 #include "IMB_imbuf_types.h"
55 #include "IMB_imbuf.h"
56
57 #include "DNA_action_types.h"
58 #include "DNA_armature_types.h"
59 #include "DNA_brush_types.h"
60 #include "DNA_camera_types.h"
61 #include "DNA_constraint_types.h"
62 #include "DNA_curve_types.h"
63 #include "DNA_group_types.h"
64 #include "DNA_gpencil_types.h"
65 #include "DNA_image_types.h"
66 #include "DNA_key_types.h"
67 #include "DNA_lamp_types.h"
68 #include "DNA_lattice_types.h"
69 #include "DNA_mesh_types.h"
70 #include "DNA_meshdata_types.h"
71 #include "DNA_meta_types.h"
72 #include "DNA_modifier_types.h"
73 #include "DNA_object_force.h"
74 #include "DNA_object_types.h"
75 #include "DNA_particle_types.h"
76 #include "DNA_screen_types.h"
77 #include "DNA_scene_types.h"
78 #include "DNA_space_types.h"
79 #include "DNA_texture_types.h"
80 #include "DNA_userdef_types.h"
81 #include "DNA_view3d_types.h"
82 #include "DNA_world_types.h"
83
84 #include "BLI_blenlib.h"
85 #include "BLI_arithb.h"
86 #include "BLI_editVert.h"
87
88 #include "BKE_action.h"
89 #include "BKE_armature.h"
90 #include "BKE_anim.h"
91 #include "BKE_constraint.h"
92 #include "BKE_curve.h"
93 #include "BKE_customdata.h"
94 #include "BKE_displist.h"
95 #include "BKE_depsgraph.h"
96 #include "BKE_DerivedMesh.h"
97 #include "BKE_global.h"
98 #include "BKE_lattice.h"
99 #include "BKE_library.h"
100 #include "BKE_image.h"
101 #include "BKE_ipo.h"
102 #include "BKE_key.h"
103 #include "BKE_main.h"
104 #include "BKE_mesh.h"
105 #include "BKE_modifier.h"
106 #include "BKE_object.h"
107 #include "BKE_particle.h"
108 #include "BKE_pointcache.h"
109 #include "BKE_scene.h"
110 #include "BKE_sculpt.h"
111 #include "BKE_texture.h"
112 #include "BKE_utildefines.h"
113
114 #include "BIF_butspace.h"
115 #include "BIF_drawimage.h"
116 #include "BIF_drawgpencil.h"
117 #include "BIF_editgroup.h"
118 #include "BIF_editarmature.h"
119 #include "BIF_editmesh.h"
120 #include "BIF_editparticle.h"
121 #include "BIF_gl.h"
122 #include "BIF_glutil.h"
123 #include "BIF_interface.h"
124 #include "BIF_interface_icons.h"
125 #include "BIF_keyframing.h"
126 #include "BIF_mywindow.h"
127 #include "BIF_poseobject.h"
128 #include "BIF_previewrender.h"
129 #include "BIF_radialcontrol.h"
130 #include "BIF_resources.h"
131 #include "BIF_retopo.h"
132 #include "BIF_screen.h"
133 #include "BIF_space.h"
134
135 #ifdef WITH_VERSE
136 #include "BIF_verse.h"
137 #endif
138
139 #include "BDR_drawaction.h"
140 #include "BDR_drawmesh.h"
141 #include "BDR_drawobject.h"
142 #include "BDR_editobject.h"
143 #include "BDR_vpaint.h"
144 #include "BDR_sculptmode.h"
145 #include "BDR_gpencil.h"
146
147 #include "BSE_drawview.h"
148 #include "BSE_filesel.h"
149 #include "BSE_headerbuttons.h"
150 #include "BSE_seqaudio.h"
151 #include "BSE_sequence.h"
152 #include "BSE_trans_types.h"
153 #include "BSE_time.h"
154 #include "BSE_view.h"
155
156 #include "BPY_extern.h"
157
158 #include "RE_render_ext.h"
159
160 #include "blendef.h"
161 #include "mydevice.h"
162 #include "butspace.h"  // event codes
163
164 #include "BIF_transform.h"
165
166 #include "RE_pipeline.h"        // make_stars
167
168 #include "GPU_draw.h"
169 #include "GPU_material.h"
170
171 #include "multires.h"
172
173 /* For MULTISAMPLE_ARB #define.
174    Note that older systems like irix 
175    may not have this, and will need a #ifdef
176    to disable it.*/
177 /* #include "GL/glext.h" Disabled for release, to avoid possibly breaking platforms.
178    Instead, the define we need will just be #defined if it's not in the platform opengl.h.
179 */
180
181 /* Modules used */
182 #include "radio.h"
183
184 /* locals */
185 //static void drawname(Object *ob);
186
187 static void star_stuff_init_func(void)
188 {
189         cpack(-1);
190         glPointSize(1.0);
191         glBegin(GL_POINTS);
192 }
193 static void star_stuff_vertex_func(float* i)
194 {
195         glVertex3fv(i);
196 }
197 static void star_stuff_term_func(void)
198 {
199         glEnd();
200 }
201
202 void circf(float x, float y, float rad)
203 {
204         GLUquadricObj *qobj = gluNewQuadric(); 
205         
206         gluQuadricDrawStyle(qobj, GLU_FILL); 
207         
208         glPushMatrix(); 
209         
210         glTranslatef(x,  y, 0.); 
211         
212         gluDisk( qobj, 0.0,  rad, 32, 1); 
213         
214         glPopMatrix(); 
215         
216         gluDeleteQuadric(qobj);
217 }
218
219 void circ(float x, float y, float rad)
220 {
221         GLUquadricObj *qobj = gluNewQuadric(); 
222         
223         gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
224         
225         glPushMatrix(); 
226         
227         glTranslatef(x,  y, 0.); 
228         
229         gluDisk( qobj, 0.0,  rad, 32, 1); 
230         
231         glPopMatrix(); 
232         
233         gluDeleteQuadric(qobj);
234 }
235
236 /* **********  ********** */
237
238 static void draw_bgpic(void)
239 {
240         BGpic *bgpic;
241         Image *ima;
242         ImBuf *ibuf= NULL;
243         float vec[4], fac, asp, zoomx, zoomy;
244         float x1, y1, x2, y2, cx, cy;
245         
246         bgpic= G.vd->bgpic;
247         if(bgpic==NULL) return;
248         
249         ima= bgpic->ima;
250         
251         if(ima)
252                 ibuf= BKE_image_get_ibuf(ima, &bgpic->iuser);
253         if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL) ) 
254                 return;
255         if(ibuf->channels!=4)
256                 return;
257         if(ibuf->rect==NULL)
258                 IMB_rect_from_float(ibuf);
259         
260         if(G.vd->persp==2) {
261                 rctf vb;
262
263                 calc_viewborder(G.vd, &vb);
264
265                 x1= vb.xmin;
266                 y1= vb.ymin;
267                 x2= vb.xmax;
268                 y2= vb.ymax;
269         }
270         else {
271                 float sco[2];
272
273                 /* calc window coord */
274                 initgrabz(0.0, 0.0, 0.0);
275                 window_to_3d(vec, 1, 0);
276                 fac= MAX3( fabs(vec[0]), fabs(vec[1]), fabs(vec[1]) );
277                 fac= 1.0/fac;
278         
279                 asp= ( (float)ibuf->y)/(float)ibuf->x;
280
281                 vec[0] = vec[1] = vec[2] = 0.0;
282                 view3d_project_float(curarea, vec, sco, G.vd->persmat);
283                 cx = sco[0];
284                 cy = sco[1];
285         
286                 x1=  cx+ fac*(bgpic->xof-bgpic->size);
287                 y1=  cy+ asp*fac*(bgpic->yof-bgpic->size);
288                 x2=  cx+ fac*(bgpic->xof+bgpic->size);
289                 y2=  cy+ asp*fac*(bgpic->yof+bgpic->size);
290         }
291         
292         /* complete clip? */
293         
294         if(x2 < 0 ) return;
295         if(y2 < 0 ) return;
296         if(x1 > curarea->winx ) return;
297         if(y1 > curarea->winy ) return;
298         
299         zoomx= (x2-x1)/ibuf->x;
300         zoomy= (y2-y1)/ibuf->y;
301         
302         /* for some reason; zoomlevels down refuses to use GL_ALPHA_SCALE */
303         if(zoomx < 1.0f || zoomy < 1.0f) {
304                 float tzoom= MIN2(zoomx, zoomy);
305                 int mip= 0;
306                 
307                 if(ibuf->mipmap[0]==NULL)
308                         IMB_makemipmap(ibuf, 0);
309                 
310                 while(tzoom < 1.0f && mip<8 && ibuf->mipmap[mip]) {
311                         tzoom*= 2.0f;
312                         zoomx*= 2.0f;
313                         zoomy*= 2.0f;
314                         mip++;
315                 }
316                 if(mip>0)
317                         ibuf= ibuf->mipmap[mip-1];
318         }
319         
320         if(G.vd->zbuf) glDisable(GL_DEPTH_TEST);
321
322         glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA); 
323          
324         glMatrixMode(GL_PROJECTION);
325         glPushMatrix();
326         glMatrixMode(GL_MODELVIEW);
327         glPushMatrix();
328         
329         glaDefine2DArea(&curarea->winrct);
330
331         glEnable(GL_BLEND);
332
333         glPixelZoom(zoomx, zoomy);
334         glColor4f(1.0, 1.0, 1.0, 1.0-bgpic->blend);
335         glaDrawPixelsTex(x1, y1, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect);
336         
337         glPixelZoom(1.0, 1.0);
338         glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
339
340         glMatrixMode(GL_PROJECTION);
341         glPopMatrix();
342         glMatrixMode(GL_MODELVIEW);
343         glPopMatrix();
344         
345         glDisable(GL_BLEND);
346         if(G.vd->zbuf) glEnable(GL_DEPTH_TEST);
347         
348         areawinset(curarea->win);       // restore viewport / scissor
349 }
350
351 static void drawgrid_draw(float wx, float wy, float x, float y, float dx)
352 {
353         float fx, fy;
354         
355         x+= (wx); 
356         y+= (wy);
357         fx= x/dx;
358         fx= x-dx*floor(fx);
359         
360         while(fx< curarea->winx) {
361                 fdrawline(fx,  0.0,  fx,  (float)curarea->winy); 
362                 fx+= dx; 
363         }
364
365         fy= y/dx;
366         fy= y-dx*floor(fy);
367         
368
369         while(fy< curarea->winy) {
370                 fdrawline(0.0,  fy,  (float)curarea->winx,  fy); 
371                 fy+= dx;
372         }
373
374 }
375
376 // not intern, called in editobject for constraint axis too
377 void make_axis_color(char *col, char *col2, char axis)
378 {
379         if(axis=='x') {
380                 col2[0]= col[0]>219?255:col[0]+36;
381                 col2[1]= col[1]<26?0:col[1]-26;
382                 col2[2]= col[2]<26?0:col[2]-26;
383         }
384         else if(axis=='y') {
385                 col2[0]= col[0]<46?0:col[0]-36;
386                 col2[1]= col[1]>189?255:col[1]+66;
387                 col2[2]= col[2]<46?0:col[2]-36; 
388         }
389         else {
390                 col2[0]= col[0]<26?0:col[0]-26; 
391                 col2[1]= col[1]<26?0:col[1]-26; 
392                 col2[2]= col[2]>209?255:col[2]+46;
393         }
394         
395 }
396
397 static void drawgrid(void)
398 {
399         /* extern short bgpicmode; */
400         float wx, wy, x, y, fw, fx, fy, dx;
401         float vec4[4];
402         char col[3], col2[3];
403         short sublines = G.vd->gridsubdiv;
404         
405         vec4[0]=vec4[1]=vec4[2]=0.0; 
406         vec4[3]= 1.0;
407         Mat4MulVec4fl(G.vd->persmat, vec4);
408         fx= vec4[0]; 
409         fy= vec4[1]; 
410         fw= vec4[3];
411
412         wx= (curarea->winx/2.0);        /* because of rounding errors, grid at wrong location */
413         wy= (curarea->winy/2.0);
414
415         x= (wx)*fx/fw;
416         y= (wy)*fy/fw;
417
418         vec4[0]=vec4[1]=G.vd->grid; 
419         vec4[2]= 0.0;
420         vec4[3]= 1.0;
421         Mat4MulVec4fl(G.vd->persmat, vec4);
422         fx= vec4[0]; 
423         fy= vec4[1]; 
424         fw= vec4[3];
425
426         dx= fabs(x-(wx)*fx/fw);
427         if(dx==0) dx= fabs(y-(wy)*fy/fw);
428         
429         glDepthMask(0);         // disable write in zbuffer
430
431         /* check zoom out */
432         BIF_ThemeColor(TH_GRID);
433         persp(PERSP_WIN);
434         
435         if(dx<6.0) {
436                 G.vd->gridview*= sublines;
437                 dx*= sublines;
438                 
439                 if(dx<6.0) {    
440                         G.vd->gridview*= sublines;
441                         dx*= sublines;
442                         
443                         if(dx<6.0) {
444                                 G.vd->gridview*= sublines;
445                                 dx*=sublines;
446                                 if(dx<6.0);
447                                 else {
448                                         BIF_ThemeColor(TH_GRID);
449                                         drawgrid_draw(wx, wy, x, y, dx);
450                                 }
451                         }
452                         else {  // start blending out
453                                 BIF_ThemeColorBlend(TH_BACK, TH_GRID, dx/60.0);
454                                 drawgrid_draw(wx, wy, x, y, dx);
455                         
456                                 BIF_ThemeColor(TH_GRID);
457                                 drawgrid_draw(wx, wy, x, y, sublines*dx);
458                         }
459                 }
460                 else {  // start blending out (6 < dx < 60)
461                         BIF_ThemeColorBlend(TH_BACK, TH_GRID, dx/60.0);
462                         drawgrid_draw(wx, wy, x, y, dx);
463                         
464                         BIF_ThemeColor(TH_GRID);
465                         drawgrid_draw(wx, wy, x, y, sublines*dx);
466                 }
467         }
468         else {
469                 if(dx>60.0) {           // start blending in
470                         G.vd->gridview/= sublines;
471                         dx/= sublines;                  
472                         if(dx>60.0) {           // start blending in
473                                 G.vd->gridview/= sublines;
474                                 dx/= sublines;
475                                 if(dx>60.0) {
476                                         BIF_ThemeColor(TH_GRID);
477                                         drawgrid_draw(wx, wy, x, y, dx);
478                                 }
479                                 else {
480                                         BIF_ThemeColorBlend(TH_BACK, TH_GRID, dx/60.0);
481                                         drawgrid_draw(wx, wy, x, y, dx);
482                                         BIF_ThemeColor(TH_GRID);
483                                         drawgrid_draw(wx, wy, x, y, dx*sublines);
484                                 }
485                         }
486                         else {
487                                 BIF_ThemeColorBlend(TH_BACK, TH_GRID, dx/60.0);
488                                 drawgrid_draw(wx, wy, x, y, dx);
489                                 BIF_ThemeColor(TH_GRID);                                
490                                 drawgrid_draw(wx, wy, x, y, dx*sublines);
491                         }
492                 }
493                 else {
494                         BIF_ThemeColorBlend(TH_BACK, TH_GRID, dx/60.0);
495                         drawgrid_draw(wx, wy, x, y, dx);
496                         BIF_ThemeColor(TH_GRID);
497                         drawgrid_draw(wx, wy, x, y, dx*sublines);
498                 }
499         }
500
501         x+= (wx); 
502         y+= (wy);
503         BIF_GetThemeColor3ubv(TH_GRID, col);
504
505         setlinestyle(0);
506         
507         /* center cross */
508         if(G.vd->view==3) make_axis_color(col, col2, 'y');
509         else make_axis_color(col, col2, 'x');
510         glColor3ubv((GLubyte *)col2);
511         
512         fdrawline(0.0,  y,  (float)curarea->winx,  y); 
513         
514         if(G.vd->view==7) make_axis_color(col, col2, 'y');
515         else make_axis_color(col, col2, 'z');
516         glColor3ubv((GLubyte *)col2);
517
518         fdrawline(x, 0.0, x, (float)curarea->winy); 
519
520         glDepthMask(1);         // enable write in zbuffer
521         persp(PERSP_VIEW);
522 }
523
524
525
526 static void drawfloor(void)
527 {
528         View3D *vd;
529         float vert[3], grid;
530         int a, gridlines, emphasise;
531         char col[3], col2[3];
532         short draw_line = 0;
533                 
534         vd= curarea->spacedata.first;
535
536         vert[2]= 0.0;
537
538         if(vd->gridlines<3) return;
539         
540         if(G.vd->zbuf && G.obedit) glDepthMask(0);      // for zbuffer-select
541         
542         gridlines= vd->gridlines/2;
543         grid= gridlines*vd->grid;
544         
545         BIF_GetThemeColor3ubv(TH_GRID, col);
546         BIF_GetThemeColor3ubv(TH_BACK, col2);
547         
548         /* emphasise division lines lighter instead of darker, if background is darker than grid */
549         if ( ((col[0]+col[1]+col[2])/3+10) > (col2[0]+col2[1]+col2[2])/3 )
550                 emphasise = 20;
551         else
552                 emphasise = -10;
553         
554         /* draw the Y axis and/or grid lines */
555         for(a= -gridlines;a<=gridlines;a++) {
556                 if(a==0) {
557                         /* check for the 'show Y axis' preference */
558                         if (vd->gridflag & V3D_SHOW_Y) { 
559                                 make_axis_color(col, col2, 'y');
560                                 glColor3ubv((GLubyte *)col2);
561                                 
562                                 draw_line = 1;
563                         } else if (vd->gridflag & V3D_SHOW_FLOOR) {
564                                 BIF_ThemeColorShade(TH_GRID, emphasise);
565                         } else {
566                                 draw_line = 0;
567                         }
568                 } else {
569                         /* check for the 'show grid floor' preference */
570                         if (vd->gridflag & V3D_SHOW_FLOOR) {
571                                 if( (a % 10)==0) {
572                                         BIF_ThemeColorShade(TH_GRID, emphasise);
573                                 }
574                                 else BIF_ThemeColorShade(TH_GRID, 10);
575                                 
576                                 draw_line = 1;
577                         } else {
578                                 draw_line = 0;
579                         }
580                 }
581                 
582                 if (draw_line) {
583                         glBegin(GL_LINE_STRIP);
584                 vert[0]= a*vd->grid;
585                 vert[1]= grid;
586                 glVertex3fv(vert);
587                 vert[1]= -grid;
588                 glVertex3fv(vert);
589                         glEnd();
590                 }
591         }
592         
593         /* draw the X axis and/or grid lines */
594         for(a= -gridlines;a<=gridlines;a++) {
595                 if(a==0) {
596                         /* check for the 'show X axis' preference */
597                         if (vd->gridflag & V3D_SHOW_X) { 
598                                 make_axis_color(col, col2, 'x');
599                                 glColor3ubv((GLubyte *)col2);
600                                 
601                                 draw_line = 1;
602                         } else if (vd->gridflag & V3D_SHOW_FLOOR) {
603                                 BIF_ThemeColorShade(TH_GRID, emphasise);
604                         } else {
605                                 draw_line = 0;
606                         }
607                 } else {
608                         /* check for the 'show grid floor' preference */
609                         if (vd->gridflag & V3D_SHOW_FLOOR) {
610                                 if( (a % 10)==0) {
611                                         BIF_ThemeColorShade(TH_GRID, emphasise);
612                                 }
613                                 else BIF_ThemeColorShade(TH_GRID, 10);
614                                 
615                                 draw_line = 1;
616                         } else {
617                                 draw_line = 0;
618                         }
619                 }
620                 
621                 if (draw_line) {
622                         glBegin(GL_LINE_STRIP);
623                 vert[1]= a*vd->grid;
624                 vert[0]= grid;
625                 glVertex3fv(vert );
626                 vert[0]= -grid;
627                 glVertex3fv(vert);
628                         glEnd();
629                 }
630         }
631         
632         /* draw the Z axis line */      
633         /* check for the 'show Z axis' preference */
634         if (vd->gridflag & V3D_SHOW_Z) {
635                 make_axis_color(col, col2, 'z');
636                 glColor3ubv((GLubyte *)col2);
637                 
638                 glBegin(GL_LINE_STRIP);
639                 vert[0]= 0;
640                 vert[1]= 0;
641                 vert[2]= grid;
642                 glVertex3fv(vert );
643                 vert[2]= -grid;
644                 glVertex3fv(vert);
645                 glEnd();
646         }
647
648         if(G.vd->zbuf && G.obedit) glDepthMask(1);      
649
650 }
651
652 static void drawcursor(View3D *v3d)
653 {
654         short mx,my,co[2];
655         int flag;
656         
657         /* we dont want the clipping for cursor */
658         flag= v3d->flag;
659         v3d->flag= 0;
660         project_short( give_cursor(), co);
661         v3d->flag= flag;
662         
663         mx = co[0];
664         my = co[1];
665
666         if(mx!=IS_CLIPPED) {
667                 setlinestyle(0); 
668                 cpack(0xFF);
669                 circ((float)mx, (float)my, 10.0);
670                 setlinestyle(4); 
671                 cpack(0xFFFFFF);
672                 circ((float)mx, (float)my, 10.0);
673                 setlinestyle(0);
674                 cpack(0x0);
675                 
676                 sdrawline(mx-20, my, mx-5, my);
677                 sdrawline(mx+5, my, mx+20, my);
678                 sdrawline(mx, my-20, mx, my-5);
679                 sdrawline(mx, my+5, mx, my+20);
680         }
681 }
682
683 /* ********* custom clipping *********** */
684
685 static void view3d_draw_clipping(View3D *v3d)
686 {
687         BoundBox *bb= v3d->clipbb;
688         
689         BIF_ThemeColorShade(TH_BACK, -8);
690         
691         glBegin(GL_QUADS);
692
693         glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[1]); glVertex3fv(bb->vec[2]); glVertex3fv(bb->vec[3]);
694         glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[5]); glVertex3fv(bb->vec[1]);
695         glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[6]); glVertex3fv(bb->vec[5]);
696         glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[3]); glVertex3fv(bb->vec[2]); glVertex3fv(bb->vec[6]);
697         glVertex3fv(bb->vec[1]); glVertex3fv(bb->vec[5]); glVertex3fv(bb->vec[6]); glVertex3fv(bb->vec[2]);
698         glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[3]);
699         
700         glEnd();
701 }
702
703 void view3d_set_clipping(View3D *v3d)
704 {
705         double plane[4];
706         int a;
707         
708         for(a=0; a<4; a++) {
709                 QUATCOPY(plane, v3d->clip[a]);
710                 glClipPlane(GL_CLIP_PLANE0+a, plane);
711                 glEnable(GL_CLIP_PLANE0+a);
712         }
713 }
714
715 void view3d_clr_clipping(void)
716 {
717         int a;
718         
719         for(a=0; a<4; a++) {
720                 glDisable(GL_CLIP_PLANE0+a);
721         }
722 }
723
724 int view3d_test_clipping(View3D *v3d, float *vec)
725 {
726         /* vec in world coordinates, returns 1 if clipped */
727         float view[3];
728         
729         VECCOPY(view, vec);
730         
731         if(0.0f < v3d->clip[0][3] + INPR(view, v3d->clip[0]))
732                 if(0.0f < v3d->clip[1][3] + INPR(view, v3d->clip[1]))
733                         if(0.0f < v3d->clip[2][3] + INPR(view, v3d->clip[2]))
734                                 if(0.0f < v3d->clip[3][3] + INPR(view, v3d->clip[3]))
735                                         return 0;
736
737         return 1;
738 }
739
740 /* ********* end custom clipping *********** */
741
742 static void view3d_get_viewborder_size(View3D *v3d, float size_r[2])
743 {
744         float winmax= MAX2(v3d->area->winx, v3d->area->winy);
745         float aspect= (float) (G.scene->r.xsch*G.scene->r.xasp)/(G.scene->r.ysch*G.scene->r.yasp);
746
747         if(aspect>1.0) {
748                 size_r[0]= winmax;
749                 size_r[1]= winmax/aspect;
750         } else {
751                 size_r[0]= winmax*aspect;
752                 size_r[1]= winmax;
753         }
754 }
755
756 void calc_viewborder(struct View3D *v3d, rctf *viewborder_r)
757 {
758         float zoomfac, size[2];
759         float dx= 0.0f, dy= 0.0f;
760         
761         view3d_get_viewborder_size(v3d, size);
762
763                 /* magic zoom calculation, no idea what
764              * it signifies, if you find out, tell me! -zr
765                  */
766         /* simple, its magic dude!
767          * well, to be honest, this gives a natural feeling zooming
768          * with multiple keypad presses (ton)
769          */
770         
771         zoomfac= (M_SQRT2 + v3d->camzoom/50.0);
772         zoomfac= (zoomfac*zoomfac)*0.25;
773         
774         size[0]= size[0]*zoomfac;
775         size[1]= size[1]*zoomfac;
776
777                 /* center in window */
778         viewborder_r->xmin= 0.5*v3d->area->winx - 0.5*size[0];
779         viewborder_r->ymin= 0.5*v3d->area->winy - 0.5*size[1];
780         viewborder_r->xmax= viewborder_r->xmin + size[0];
781         viewborder_r->ymax= viewborder_r->ymin + size[1];
782         
783         dx= v3d->area->winx*G.vd->camdx*zoomfac*2.0f;
784         dy= v3d->area->winy*G.vd->camdy*zoomfac*2.0f;
785         
786         /* apply offset */
787         viewborder_r->xmin-= dx;
788         viewborder_r->ymin-= dy;
789         viewborder_r->xmax-= dx;
790         viewborder_r->ymax-= dy;
791         
792         if(v3d->camera && v3d->camera->type==OB_CAMERA) {
793                 Camera *cam= v3d->camera->data;
794                 float w = viewborder_r->xmax - viewborder_r->xmin;
795                 float h = viewborder_r->ymax - viewborder_r->ymin;
796                 float side = MAX2(w, h);
797
798                 viewborder_r->xmin+= cam->shiftx*side;
799                 viewborder_r->xmax+= cam->shiftx*side;
800                 viewborder_r->ymin+= cam->shifty*side;
801                 viewborder_r->ymax+= cam->shifty*side;
802         }
803 }
804
805 void view3d_set_1_to_1_viewborder(View3D *v3d)
806 {
807         float size[2];
808         int im_width= (G.scene->r.size*G.scene->r.xsch)/100;
809
810         view3d_get_viewborder_size(v3d, size);
811
812         v3d->camzoom= (sqrt(4.0*im_width/size[0]) - M_SQRT2)*50.0;
813         v3d->camzoom= CLAMPIS(v3d->camzoom, -30, 300);
814 }
815
816
817 static void drawviewborder_flymode(void)        
818 {
819         /* draws 4 edge brackets that frame the safe area where the
820         mouse can move during fly mode without spinning the view */
821         float x1, x2, y1, y2;
822         
823         x1= 0.45*(float)curarea->winx;
824         y1= 0.45*(float)curarea->winy;
825         x2= 0.55*(float)curarea->winx;
826         y2= 0.55*(float)curarea->winy;
827         cpack(0);
828         
829         
830         glBegin(GL_LINES);
831         /* bottom left */
832         glVertex2f(x1,y1); 
833         glVertex2f(x1,y1+5);
834         
835         glVertex2f(x1,y1); 
836         glVertex2f(x1+5,y1);
837
838         /* top right */
839         glVertex2f(x2,y2); 
840         glVertex2f(x2,y2-5);
841         
842         glVertex2f(x2,y2); 
843         glVertex2f(x2-5,y2);
844         
845         /* top left */
846         glVertex2f(x1,y2); 
847         glVertex2f(x1,y2-5);
848         
849         glVertex2f(x1,y2); 
850         glVertex2f(x1+5,y2);
851         
852         /* bottom right */
853         glVertex2f(x2,y1); 
854         glVertex2f(x2,y1+5);
855         
856         glVertex2f(x2,y1); 
857         glVertex2f(x2-5,y1);
858         glEnd();        
859 }
860
861
862 static void drawviewborder(void)
863 {
864         extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad);          // interface_panel.c
865         float fac, a;
866         float x1, x2, y1, y2;
867         float x3, y3, x4, y4;
868         rctf viewborder;
869         Camera *ca= NULL;
870
871         if(G.vd->camera==NULL)
872                 return;
873         if(G.vd->camera->type==OB_CAMERA)
874                 ca = G.vd->camera->data;
875         
876         calc_viewborder(G.vd, &viewborder);
877         x1= viewborder.xmin;
878         y1= viewborder.ymin;
879         x2= viewborder.xmax;
880         y2= viewborder.ymax;
881
882         /* passepartout, specified in camera edit buttons */
883         if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001) {
884                 if (ca->passepartalpha == 1.0) {
885                         glColor3f(0, 0, 0);
886                 } else {
887                         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
888                         glEnable(GL_BLEND);
889                         glColor4f(0, 0, 0, ca->passepartalpha);
890                 }
891                 if (x1 > 0.0)
892                         glRectf(0.0, (float)curarea->winy, x1, 0.0);
893                 if (x2 < (float)curarea->winx)
894                         glRectf(x2, (float)curarea->winy, (float)curarea->winx, 0.0);
895                 if (y2 < (float)curarea->winy)
896                         glRectf(x1, (float)curarea->winy, x2, y2);
897                 if (y2 > 0.0) 
898                         glRectf(x1, y1, x2, 0.0);
899
900                 glDisable(GL_BLEND);
901         }
902         
903         /* edge */
904         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
905         
906         setlinestyle(0);
907         BIF_ThemeColor(TH_BACK);
908         glRectf(x1, y1, x2, y2);
909         
910         setlinestyle(3);
911         BIF_ThemeColor(TH_WIRE);
912         glRectf(x1, y1, x2, y2);
913                 
914         /* camera name - draw in highlighted text color */
915         if (ca && (ca->flag & CAM_SHOWNAME)) {
916                 BIF_ThemeColor(TH_TEXT_HI);
917                 glRasterPos2f(x1, y1-15);
918                 
919                 BMF_DrawString(G.font, G.vd->camera->id.name+2);
920                 BIF_ThemeColor(TH_WIRE);
921         }
922
923
924         /* border */
925         if(G.scene->r.mode & R_BORDER) {
926                 
927                 cpack(0);
928                 x3= x1+ G.scene->r.border.xmin*(x2-x1);
929                 y3= y1+ G.scene->r.border.ymin*(y2-y1);
930                 x4= x1+ G.scene->r.border.xmax*(x2-x1);
931                 y4= y1+ G.scene->r.border.ymax*(y2-y1);
932                 
933                 cpack(0x4040FF);
934                 glRectf(x3,  y3,  x4,  y4); 
935         }
936
937         /* safety border */
938         if (ca && (ca->flag & CAM_SHOWTITLESAFE)) {
939                 fac= 0.1;
940                 
941                 a= fac*(x2-x1);
942                 x1+= a; 
943                 x2-= a;
944         
945                 a= fac*(y2-y1);
946                 y1+= a;
947                 y2-= a;
948         
949                 BIF_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0);
950                 
951                 uiSetRoundBox(15);
952                 gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, 12.0);
953         }
954         
955         setlinestyle(0);
956         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
957
958 }
959
960 void backdrawview3d(int test)
961 {
962         struct Base *base;
963
964 /*for 2.43 release, don't use glext and just define the constant.
965   this to avoid possibly breaking platforms before release.*/
966 #ifndef GL_MULTISAMPLE_ARB
967         #define GL_MULTISAMPLE_ARB      0x809D
968 #endif
969
970 #ifdef GL_MULTISAMPLE_ARB
971         int m;
972 #endif
973
974         if(G.f & G_VERTEXPAINT || G.f & G_WEIGHTPAINT || G.f & G_TEXTUREPAINT);
975         else if(G.obedit && G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT));
976         else {
977                 G.vd->flag &= ~V3D_NEEDBACKBUFDRAW;
978                 return;
979         }
980
981         if( !(G.vd->flag & V3D_NEEDBACKBUFDRAW) ) return;
982
983         if(test) {
984                 if(qtest()) {
985                         addafterqueue(curarea->win, BACKBUFDRAW, 1);
986                         return;
987                 }
988         }
989         persp(PERSP_VIEW);
990
991         /*Disable FSAA for backbuffer selection.  
992         
993         Only works if GL_MULTISAMPLE_ARB is defined by the header
994         file, which is should be for every OS that supports FSAA.*/
995
996 #ifdef GL_MULTISAMPLE_ARB
997         m = glIsEnabled(GL_MULTISAMPLE_ARB);
998         if (m) glDisable(GL_MULTISAMPLE_ARB);
999 #endif
1000
1001 #ifdef __APPLE__
1002         glDrawBuffer(GL_AUX0);
1003 #endif  
1004         if(G.vd->drawtype > OB_WIRE) G.vd->zbuf= TRUE;
1005         curarea->win_swap &= ~WIN_BACK_OK;
1006         
1007         glDisable(GL_DITHER);
1008
1009         glClearColor(0.0, 0.0, 0.0, 0.0); 
1010         if(G.vd->zbuf) {
1011                 glEnable(GL_DEPTH_TEST);
1012                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1013         }
1014         else {
1015                 glClear(GL_COLOR_BUFFER_BIT);
1016                 glDisable(GL_DEPTH_TEST);
1017         }
1018         
1019         if(G.vd->flag & V3D_CLIPPING)
1020                 view3d_set_clipping(G.vd);
1021         
1022         G.f |= G_BACKBUFSEL;
1023         
1024         base= (G.scene->basact);
1025         if(base && (base->lay & G.vd->lay)) {
1026                 draw_object_backbufsel(base->object);
1027         }
1028
1029         G.vd->flag &= ~V3D_NEEDBACKBUFDRAW;
1030
1031         G.f &= ~G_BACKBUFSEL;
1032         G.vd->zbuf= FALSE; 
1033         glDisable(GL_DEPTH_TEST);
1034         glEnable(GL_DITHER);
1035
1036 #ifdef __APPLE__
1037         glDrawBuffer(GL_BACK); /* we were in aux buffers */
1038 #endif
1039
1040         if(G.vd->flag & V3D_CLIPPING)
1041                 view3d_clr_clipping();
1042
1043 #ifdef GL_MULTISAMPLE_ARB
1044         if (m) glEnable(GL_MULTISAMPLE_ARB);
1045 #endif
1046
1047         /* it is important to end a view in a transform compatible with buttons */
1048         persp(PERSP_WIN);  // set ortho
1049         bwin_scalematrix(curarea->win, G.vd->blockscale, G.vd->blockscale, G.vd->blockscale);
1050
1051 }
1052
1053 void check_backbuf(void)
1054 {
1055         if(G.vd->flag & V3D_NEEDBACKBUFDRAW)
1056                 backdrawview3d(0);
1057 }
1058
1059 /* samples a single pixel (copied from vpaint) */
1060 unsigned int sample_backbuf(int x, int y)
1061 {
1062         unsigned int col;
1063         
1064         if(x>=curarea->winx || y>=curarea->winy) return 0;
1065         x+= curarea->winrct.xmin;
1066         y+= curarea->winrct.ymin;
1067         
1068         check_backbuf(); // actually not needed for apple
1069
1070 #ifdef __APPLE__
1071         glReadBuffer(GL_AUX0);
1072 #endif
1073         glReadPixels(x,  y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,  &col);
1074         glReadBuffer(GL_BACK);  
1075         
1076         if(G.order==B_ENDIAN) SWITCH_INT(col);
1077         
1078         return framebuffer_to_index(col);
1079 }
1080
1081 /* reads full rect, converts indices */
1082 ImBuf *read_backbuf(short xmin, short ymin, short xmax, short ymax)
1083 {
1084         unsigned int *dr, *rd;
1085         struct ImBuf *ibuf, *ibuf1;
1086         int a;
1087         short xminc, yminc, xmaxc, ymaxc, xs, ys;
1088         
1089         /* clip */
1090         if(xmin<0) xminc= 0; else xminc= xmin;
1091         if(xmax>=curarea->winx) xmaxc= curarea->winx-1; else xmaxc= xmax;
1092         if(xminc > xmaxc) return NULL;
1093
1094         if(ymin<0) yminc= 0; else yminc= ymin;
1095         if(ymax>=curarea->winy) ymaxc= curarea->winy-1; else ymaxc= ymax;
1096         if(yminc > ymaxc) return NULL;
1097         
1098         ibuf= IMB_allocImBuf((xmaxc-xminc+1), (ymaxc-yminc+1), 32, IB_rect,0);
1099
1100         check_backbuf(); // actually not needed for apple
1101         
1102 #ifdef __APPLE__
1103         glReadBuffer(GL_AUX0);
1104 #endif
1105         glReadPixels(curarea->winrct.xmin+xminc, curarea->winrct.ymin+yminc, (xmaxc-xminc+1), (ymaxc-yminc+1), GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
1106         glReadBuffer(GL_BACK);  
1107
1108         if(G.order==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
1109
1110         a= (xmaxc-xminc+1)*(ymaxc-yminc+1);
1111         dr= ibuf->rect;
1112         while(a--) {
1113                 if(*dr) *dr= framebuffer_to_index(*dr);
1114                 dr++;
1115         }
1116         
1117         /* put clipped result back, if needed */
1118         if(xminc==xmin && xmaxc==xmax && yminc==ymin && ymaxc==ymax) 
1119                 return ibuf;
1120         
1121         ibuf1= IMB_allocImBuf( (xmax-xmin+1),(ymax-ymin+1),32,IB_rect,0);
1122         rd= ibuf->rect;
1123         dr= ibuf1->rect;
1124                 
1125         for(ys= ymin; ys<=ymax; ys++) {
1126                 for(xs= xmin; xs<=xmax; xs++, dr++) {
1127                         if( xs>=xminc && xs<=xmaxc && ys>=yminc && ys<=ymaxc) {
1128                                 *dr= *rd;
1129                                 rd++;
1130                         }
1131                 }
1132         }
1133         IMB_freeImBuf(ibuf);
1134         return ibuf1;
1135 }
1136
1137 /* smart function to sample a rect spiralling outside, nice for backbuf selection */
1138 unsigned int sample_backbuf_rect(short mval[2], int size, unsigned int min, unsigned int max, int *dist, short strict, unsigned int (*indextest)(unsigned int index))
1139 {
1140         struct ImBuf *buf;
1141         unsigned int *bufmin, *bufmax, *tbuf;
1142         int minx, miny;
1143         int a, b, rc, nr, amount, dirvec[4][2];
1144         int distance=0;
1145         unsigned int index = 0;
1146         short indexok = 0;      
1147
1148         amount= (size-1)/2;
1149
1150         minx = mval[0]-(amount+1);
1151         miny = mval[1]-(amount+1);
1152         buf = read_backbuf(minx, miny, minx+size-1, miny+size-1);
1153         if (!buf) return 0;
1154
1155         rc= 0;
1156         
1157         dirvec[0][0]= 1; dirvec[0][1]= 0;
1158         dirvec[1][0]= 0; dirvec[1][1]= -size;
1159         dirvec[2][0]= -1; dirvec[2][1]= 0;
1160         dirvec[3][0]= 0; dirvec[3][1]= size;
1161         
1162         bufmin = buf->rect;
1163         tbuf = buf->rect;
1164         bufmax = buf->rect + size*size;
1165         tbuf+= amount*size+ amount;
1166         
1167         for(nr=1; nr<=size; nr++) {
1168                 
1169                 for(a=0; a<2; a++) {
1170                         for(b=0; b<nr; b++, distance++) {
1171                                 if (*tbuf && *tbuf>=min && *tbuf<max) { //we got a hit
1172                                         if(strict){
1173                                                 indexok =  indextest(*tbuf - min+1);
1174                                                 if(indexok){
1175                                                         *dist= (short) sqrt( (float)distance   );
1176                                                         index = *tbuf - min+1;
1177                                                         goto exit; 
1178                                                 }                                               
1179                                         }
1180                                         else{
1181                                                 *dist= (short) sqrt( (float)distance ); // XXX, this distance is wrong - 
1182                                                 index = *tbuf - min+1; // messy yah, but indices start at 1
1183                                                 goto exit;
1184                                         }                       
1185                                 }
1186                                 
1187                                 tbuf+= (dirvec[rc][0]+dirvec[rc][1]);
1188                                 
1189                                 if(tbuf<bufmin || tbuf>=bufmax) {
1190                                         goto exit;
1191                                 }
1192                         }
1193                         rc++;
1194                         rc &= 3;
1195                 }
1196         }
1197
1198 exit:
1199         IMB_freeImBuf(buf);
1200         return index;
1201 }
1202
1203 #if 0
1204 static void drawname(Object *ob)
1205 {
1206         cpack(0x404040);
1207         glRasterPos3f(0.0,  0.0,  0.0);
1208         
1209         BMF_DrawString(G.font, " ");
1210         BMF_DrawString(G.font, ob->id.name+2);
1211 }
1212 #endif
1213
1214 static char *get_cfra_marker_name()
1215 {
1216         ListBase *markers= &G.scene->markers;
1217         TimeMarker *m1, *m2;
1218         
1219         /* search through markers for match */
1220         for (m1=markers->first, m2=markers->last; m1 && m2; m1=m1->next, m2=m2->prev) {
1221                 if (m1->frame==CFRA)
1222                         return m1->name;
1223                 
1224                 if (m1 == m2)
1225                         break;          
1226                 
1227                 if (m2->frame==CFRA)
1228                         return m2->name;
1229         }
1230         
1231         return NULL;
1232 }
1233
1234 /* draw info beside axes in bottom left-corner: 
1235  *      framenum, object name, bone name (if available), marker name (if available)
1236  */
1237 static void draw_selected_name(Object *ob)
1238 {
1239         char info[256], *markern;
1240         short offset=30;
1241         
1242         /* get name of marker on current frame (if available) */
1243         markern= get_cfra_marker_name();
1244         
1245         /* check if there is an object */
1246         if(ob) {
1247                 /* name(s) to display depends on type of object */
1248                 if(ob->type==OB_ARMATURE) {
1249                         bArmature *arm= ob->data;
1250                         char *name= NULL;
1251                         
1252                         /* show name of active bone too (if possible) */
1253                         if(ob==G.obedit) {
1254                                 EditBone *ebo;
1255                                 for (ebo=G.edbo.first; ebo; ebo=ebo->next){
1256                                         if ((ebo->flag & BONE_ACTIVE) && (ebo->layer & arm->layer)) {
1257                                                 name= ebo->name;
1258                                                 break;
1259                                         }
1260                                 }
1261                         }
1262                         else if(ob->pose && (ob->flag & OB_POSEMODE)) {
1263                                 bPoseChannel *pchan;
1264                                 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1265                                         if((pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer)) {
1266                                                 name= pchan->name;
1267                                                 break;
1268                                         }
1269                                 }
1270                         }
1271                         if(name && markern)
1272                                 sprintf(info, "(%d) %s %s <%s>", CFRA, ob->id.name+2, name, markern);
1273                         else if(name)
1274                                 sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, name);
1275                         else
1276                                 sprintf(info, "(%d) %s", CFRA, ob->id.name+2);
1277                 }
1278                 else if(ELEM3(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) {
1279                         Key *key= NULL;
1280                         KeyBlock *kb = NULL;
1281                         char shapes[75];
1282                         
1283                         /* try to display active shapekey too */
1284                         shapes[0] = 0;
1285                         key = ob_get_key(ob);
1286                         if(key){
1287                                 kb = BLI_findlink(&key->block, ob->shapenr-1);
1288                                 if(kb){
1289                                         sprintf(shapes, ": %s ", kb->name);             
1290                                         if(ob->shapeflag == OB_SHAPE_LOCK){
1291                                                 sprintf(shapes, "%s (Pinned)",shapes);
1292                                         }
1293                                 }
1294                         }
1295                         
1296                         if(markern)
1297                                 sprintf(info, "(%d) %s %s <%s>", CFRA, ob->id.name+2, shapes, markern);
1298                         else
1299                                 sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, shapes);
1300                 }
1301                 else {
1302                         /* standard object */
1303                         if (markern)
1304                                 sprintf(info, "(%d) %s <%s>", CFRA, ob->id.name+2, markern);
1305                         else
1306                                 sprintf(info, "(%d) %s", CFRA, ob->id.name+2);
1307                 }
1308                         
1309                 /* colour depends on whether there is a keyframe */
1310                 if (id_frame_has_keyframe((ID *)ob, frame_to_float(CFRA), G.vd->keyflags))
1311                         BIF_ThemeColor(TH_VERTEX_SELECT);
1312                 else
1313                         BIF_ThemeColor(TH_TEXT_HI);
1314         }
1315         else {
1316                 /* no object */
1317                 if (markern)
1318                         sprintf(info, "(%d) <%s>", CFRA, markern);
1319                 else
1320                         sprintf(info, "(%d)", CFRA);
1321                 
1322                 /* colour is always white */
1323                 BIF_ThemeColor(TH_TEXT_HI);
1324         }
1325         
1326         if (U.uiflag & USER_SHOW_ROTVIEWICON)
1327                 offset = 14 + (U.rvisize * 2);
1328
1329         glRasterPos2i(offset,  10);
1330         BMF_DrawString(G.fonts, info);
1331 }
1332
1333
1334 /* Draw a live substitute of the view icon, which is always shown */
1335 static void draw_view_axis(void)
1336 {
1337         const float k = U.rvisize;   /* axis size */
1338         const float toll = 0.5;      /* used to see when view is quasi-orthogonal */
1339         const float start = k + 1.0; /* axis center in screen coordinates, x=y */
1340         float ydisp = 0.0;          /* vertical displacement to allow obj info text */
1341         
1342         /* rvibright ranges approx. from original axis icon color to gizmo color */
1343         float bright = U.rvibright / 15.0f;
1344         
1345         unsigned char col[3];
1346         unsigned char gridcol[3];
1347         float colf[3];
1348         
1349         float vec[4];
1350         float dx, dy;
1351         float h, s, v;
1352         
1353         /* thickness of lines is proportional to k */
1354         /*      (log(k)-1) gives a more suitable thickness, but fps decreased by about 3 fps */
1355         glLineWidth(k / 10);
1356         //glLineWidth(log(k)-1); // a bit slow
1357         
1358         BIF_GetThemeColor3ubv(TH_GRID, (char *)gridcol);
1359         
1360         /* X */
1361         vec[0] = vec[3] = 1;
1362         vec[1] = vec[2] = 0;
1363         QuatMulVecf(G.vd->viewquat, vec);
1364         
1365         make_axis_color((char *)gridcol, (char *)col, 'x');
1366         rgb_to_hsv(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, &h, &s, &v);
1367         s = s<0.5 ? s+0.5 : 1.0;
1368         v = 0.3;
1369         v = (v<1.0-(bright) ? v+bright : 1.0);
1370         hsv_to_rgb(h, s, v, colf, colf+1, colf+2);
1371         glColor3fv(colf);
1372         
1373         dx = vec[0] * k;
1374         dy = vec[1] * k;
1375         fdrawline(start, start + ydisp, start + dx, start + dy + ydisp);
1376         if (fabs(dx) > toll || fabs(dy) > toll) {
1377                 glRasterPos2i(start + dx + 2, start + dy + ydisp + 2);
1378                 BMF_DrawString(G.fonts, "x");
1379         }
1380         
1381         /* Y */
1382         vec[1] = vec[3] = 1;
1383         vec[0] = vec[2] = 0;
1384         QuatMulVecf(G.vd->viewquat, vec);
1385         
1386         make_axis_color((char *)gridcol, (char *)col, 'y');
1387         rgb_to_hsv(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, &h, &s, &v);
1388         s = s<0.5 ? s+0.5 : 1.0;
1389         v = 0.3;
1390         v = (v<1.0-(bright) ? v+bright : 1.0);
1391         hsv_to_rgb(h, s, v, colf, colf+1, colf+2);
1392         glColor3fv(colf);
1393         
1394         dx = vec[0] * k;
1395         dy = vec[1] * k;
1396         fdrawline(start, start + ydisp, start + dx, start + dy + ydisp);
1397         if (fabs(dx) > toll || fabs(dy) > toll) {
1398                 glRasterPos2i(start + dx + 2, start + dy + ydisp + 2);
1399                 BMF_DrawString(G.fonts, "y");
1400         }
1401         
1402         /* Z */
1403         vec[2] = vec[3] = 1;
1404         vec[1] = vec[0] = 0;
1405         QuatMulVecf(G.vd->viewquat, vec);
1406         
1407         make_axis_color((char *)gridcol, (char *)col, 'z');
1408         rgb_to_hsv(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, &h, &s, &v);
1409         s = s<0.5 ? s+0.5 : 1.0;
1410         v = 0.5;
1411         v = (v<1.0-(bright) ? v+bright : 1.0);
1412         hsv_to_rgb(h, s, v, colf, colf+1, colf+2);
1413         glColor3fv(colf);
1414         
1415         dx = vec[0] * k;
1416         dy = vec[1] * k;
1417         fdrawline(start, start + ydisp, start + dx, start + dy + ydisp);
1418         if (fabs(dx) > toll || fabs(dy) > toll) {
1419                 glRasterPos2i(start + dx + 2, start + dy + ydisp + 2);
1420                 BMF_DrawString(G.fonts, "z");
1421         }
1422         
1423         /* restore line-width */
1424         glLineWidth(1.0);
1425 }
1426
1427         
1428 static void draw_view_icon(void)
1429 {
1430         BIFIconID icon;
1431         
1432         if(G.vd->view==7) icon= ICON_AXIS_TOP;
1433         else if(G.vd->view==1) icon= ICON_AXIS_FRONT;
1434         else if(G.vd->view==3) icon= ICON_AXIS_SIDE;
1435         else return ;
1436
1437         glEnable(GL_BLEND);
1438         glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA); 
1439         
1440         BIF_icon_draw(5.0, 5.0, icon);
1441         
1442         glDisable(GL_BLEND);
1443 }
1444
1445 char *view3d_get_name(View3D *v3d)
1446 {
1447         char *name = NULL;
1448         
1449         switch (v3d->view) {
1450                 case 1:
1451                         if (v3d->persp == V3D_ORTHO)
1452                                 name = (v3d->flag2 & V3D_OPP_DIRECTION_NAME) ? "Back Ortho" : "Front Ortho";
1453                         else
1454                                 name = (v3d->flag2 & V3D_OPP_DIRECTION_NAME) ? "Back Persp" : "Front Persp";
1455                         break;
1456                 case 3:
1457                         if (v3d->persp == V3D_ORTHO)
1458                                 name = (v3d->flag2 & V3D_OPP_DIRECTION_NAME) ? "Left Ortho" : "Right Ortho";
1459                         else
1460                                 name = (v3d->flag2 & V3D_OPP_DIRECTION_NAME) ? "Left Persp" : "Right Persp";
1461                         break;
1462                 case 7:
1463                         if (v3d->persp == V3D_ORTHO)
1464                                 name = (v3d->flag2 & V3D_OPP_DIRECTION_NAME) ? "Bottom Ortho" : "Top Ortho";
1465                         else
1466                                 name = (v3d->flag2 & V3D_OPP_DIRECTION_NAME) ? "Bottom Persp" : "Top Persp";
1467                         break;
1468                 default:
1469                         if (v3d->persp==V3D_CAMOB) {
1470                                 if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
1471                                         Camera *cam;
1472                                         cam = v3d->camera->data;
1473                                         name = (cam->type != CAM_ORTHO) ? "Camera Persp" : "Camera Ortho";
1474                                 } else {
1475                                         name = "Object as Camera";
1476                                 }
1477                         } else { 
1478                                 name = (v3d->persp == V3D_ORTHO) ? "User Ortho" : "User Persp";
1479                         }
1480                         break;
1481         }
1482         
1483         return name;
1484 }
1485
1486 static void draw_viewport_name(ScrArea *sa)
1487 {
1488         char *name = view3d_get_name(sa->spacedata.first);
1489         char *printable = NULL;
1490         
1491         if (G.vd->localview) {
1492                 printable = malloc(strlen(name) + strlen(" (Local)_")); /* '_' gives space for '\0' */
1493                 strcpy(printable, name);
1494                 strcat(printable, " (Local)");
1495         } else {
1496                 printable = name;
1497         }
1498
1499         if (printable) {
1500                 BIF_ThemeColor(TH_TEXT_HI);
1501                 glRasterPos2i(10,  sa->winy-20);
1502                 BMF_DrawString(G.fonts, printable);
1503         }
1504
1505         if (G.vd->localview) {
1506                 free(printable);
1507         }
1508 }
1509
1510 /* ******************* view3d space & buttons ************** */
1511
1512
1513 /* temporal struct for storing transform properties */
1514 typedef struct {
1515         float ob_eul[4];        // used for quat too....
1516         float ob_scale[3]; // need temp space due to linked values
1517         float ob_dims[3];
1518         short link_scale;
1519         float ve_median[5];
1520         int curdef;
1521         float *defweightp;
1522 } TransformProperties;
1523
1524 /* is used for both read and write... */
1525 static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim)
1526 {
1527         EditMesh *em = G.editMesh;
1528         EditVert *eve, *evedef=NULL;
1529         EditEdge *eed;
1530         MDeformVert *dvert=NULL;
1531         TransformProperties *tfp= G.vd->properties_storage;
1532         float median[5], ve_median[5];
1533         int tot, totw, totweight, totedge;
1534         char defstr[320];
1535         
1536         median[0]= median[1]= median[2]= median[3]= median[4]= 0.0;
1537         tot= totw= totweight= totedge= 0;
1538         defstr[0]= 0;
1539
1540         if(ob->type==OB_MESH) {         
1541                 eve= em->verts.first;
1542                 while(eve) {
1543                         if(eve->f & SELECT) {
1544                                 evedef= eve;
1545                                 tot++;
1546                                 VecAddf(median, median, eve->co);
1547                         }
1548                         eve= eve->next;
1549                 }
1550                 eed= em->edges.first;
1551                 while(eed) {
1552                         if((eed->f & SELECT)) {
1553                                 totedge++;
1554                                 median[3]+= eed->crease;
1555                         }
1556                         eed= eed->next;
1557                 }
1558
1559                 /* check for defgroups */
1560                 if(evedef)
1561                         dvert= CustomData_em_get(&em->vdata, evedef->data, CD_MDEFORMVERT);
1562                 if(tot==1 && dvert && dvert->totweight) {
1563                         bDeformGroup *dg;
1564                         int i, max=1, init=1;
1565                         char str[320];
1566                         
1567                         for (i=0; i<dvert->totweight; i++){
1568                                 dg = BLI_findlink (&ob->defbase, dvert->dw[i].def_nr);
1569                                 if(dg) {
1570                                         max+= snprintf(str, sizeof(str), "%s %%x%d|", dg->name, dvert->dw[i].def_nr); 
1571                                         if(max<320) strcat(defstr, str);
1572                                 }
1573                                 else printf("oh no!\n");
1574                                 if(tfp->curdef==dvert->dw[i].def_nr) {
1575                                         init= 0;
1576                                         tfp->defweightp= &dvert->dw[i].weight;
1577                                 }
1578                         }
1579                         
1580                         if(init) {      // needs new initialized 
1581                                 tfp->curdef= dvert->dw[0].def_nr;
1582                                 tfp->defweightp= &dvert->dw[0].weight;
1583                         }
1584                 }
1585         }
1586         else if(ob->type==OB_CURVE || ob->type==OB_SURF) {
1587                 extern ListBase editNurb; /* editcurve.c */
1588                 Nurb *nu;
1589                 BPoint *bp;
1590                 BezTriple *bezt;
1591                 int a;
1592                 
1593                 nu= editNurb.first;
1594                 while(nu) {
1595                         if((nu->type & 7)==CU_BEZIER) {
1596                                 bezt= nu->bezt;
1597                                 a= nu->pntsu;
1598                                 while(a--) {
1599                                         if(bezt->f2 & SELECT) {
1600                                                 VecAddf(median, median, bezt->vec[1]);
1601                                                 tot++;
1602                                                 median[4]+= bezt->weight;
1603                                                 totweight++;
1604                                         }
1605                                         else {
1606                                                 if(bezt->f1 & SELECT) {
1607                                                         VecAddf(median, median, bezt->vec[0]);
1608                                                         tot++;
1609                                                 }
1610                                                 if(bezt->f3 & SELECT) {
1611                                                         VecAddf(median, median, bezt->vec[2]);
1612                                                         tot++;
1613                                                 }
1614                                         }
1615                                         bezt++;
1616                                 }
1617                         }
1618                         else {
1619                                 bp= nu->bp;
1620                                 a= nu->pntsu*nu->pntsv;
1621                                 while(a--) {
1622                                         if(bp->f1 & SELECT) {
1623                                                 VecAddf(median, median, bp->vec);
1624                                                 median[3]+= bp->vec[3];
1625                                                 totw++;
1626                                                 tot++;
1627                                                 median[4]+= bp->weight;
1628                                                 totweight++;
1629                                         }
1630                                         bp++;
1631                                 }
1632                         }
1633                         nu= nu->next;
1634                 }
1635         }
1636         else if(ob->type==OB_LATTICE) {
1637                 BPoint *bp;
1638                 int a;
1639                 
1640                 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1641                 bp= editLatt->def;
1642                 while(a--) {
1643                         if(bp->f1 & SELECT) {
1644                                 VecAddf(median, median, bp->vec);
1645                                 tot++;
1646                                 median[4]+= bp->weight;
1647                                 totweight++;
1648                         }
1649                         bp++;
1650                 }
1651         }
1652         
1653         if(tot==0) return;
1654
1655         median[0] /= (float)tot;
1656         median[1] /= (float)tot;
1657         median[2] /= (float)tot;
1658         if(totedge) median[3] /= (float)totedge;
1659         else if(totw) median[3] /= (float)totw;
1660         if(totweight) median[4] /= (float)totweight;
1661         
1662         if(G.vd->flag & V3D_GLOBAL_STATS)
1663                 Mat4MulVecfl(ob->obmat, median);
1664         
1665         if(block) {     // buttons
1666                 int but_y;
1667                 if((ob->parent) && (ob->partype == PARBONE))    but_y = 135;
1668                 else                                                                                    but_y = 150;
1669                 
1670                 uiBlockBeginAlign(block);
1671                 uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, REDRAWVIEW3D, "Global",              160, but_y, 70, 19, &G.vd->flag, 0, 0, 0, 0, "Displays global values");
1672                 uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, REDRAWVIEW3D, "Local",              230, but_y, 70, 19, &G.vd->flag, 0, 0, 0, 0, "Displays local values");
1673                 uiBlockEndAlign(block);
1674                 
1675                 memcpy(tfp->ve_median, median, sizeof(tfp->ve_median));
1676                 
1677                 uiBlockBeginAlign(block);
1678                 if(tot==1) {
1679                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex X:", 10, 110, 290, 19, &(tfp->ve_median[0]), -lim, lim, 10, 3, "");
1680                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex Y:", 10, 90, 290, 19, &(tfp->ve_median[1]), -lim, lim, 10, 3, "");
1681                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex Z:", 10, 70, 290, 19, &(tfp->ve_median[2]), -lim, lim, 10, 3, "");
1682                         if(totw==1)
1683                                 uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex W:", 10, 50, 290, 19, &(tfp->ve_median[3]), 0.01, 100.0, 10, 3, "");
1684                         uiBlockEndAlign(block);
1685         
1686                         if(defstr[0]) {
1687                                 uiDefBut(block, LABEL, 1, "Vertex Deform Groups",               10, 40, 290, 20, NULL, 0.0, 0.0, 0, 0, "");
1688
1689                                 uiBlockBeginAlign(block);
1690                                 uiDefButF(block, NUM, B_NOP, "Weight:",                 10, 20, 150, 19, tfp->defweightp, 0.0f, 1.0f, 10, 3, "Weight value");
1691                                 uiDefButI(block, MENU, REDRAWVIEW3D, defstr,    160, 20, 140, 19, &tfp->curdef, 0.0, 0.0, 0, 0, "Current Vertex Group");
1692                                 uiBlockEndAlign(block);
1693                         }
1694                         else if(totweight)
1695                                 uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:",   10, 20, 290, 19, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, "");
1696
1697                 }
1698                 else {
1699                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median X:", 10, 110, 290, 19, &(tfp->ve_median[0]), -lim, lim, 10, 3, "");
1700                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median Y:", 10, 90, 290, 19, &(tfp->ve_median[1]), -lim, lim, 10, 3, "");
1701                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median Z:", 10, 70, 290, 19, &(tfp->ve_median[2]), -lim, lim, 10, 3, "");
1702                         if(totw==tot)
1703                                 uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median W:", 10, 50, 290, 19, &(tfp->ve_median[3]), 0.01, 100.0, 10, 3, "");
1704                         uiBlockEndAlign(block);
1705                         if(totweight)
1706                                 uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:",   10, 20, 290, 19, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, "Weight is used for SoftBody Goal");
1707                 }
1708                 
1709                 if(ob->type==OB_CURVE && (totw==0)) { /* bez curves have no w */
1710                         uiBlockBeginAlign(block);
1711                         uiDefBut(block, BUT,B_SETPT_AUTO,"Auto",        10, 44, 72, 19, 0, 0, 0, 0, 0, "Auto handles (Shift H)");
1712                         uiDefBut(block, BUT,B_SETPT_VECTOR,"Vector",82, 44, 73, 19, 0, 0, 0, 0, 0, "Vector handles (V)");
1713                         uiDefBut(block, BUT,B_SETPT_ALIGN,"Align",155, 44, 73, 19, 0, 0, 0, 0, 0, "Align handles (H Toggles)");
1714                         uiDefBut(block, BUT,B_SETPT_FREE,"Free",        227, 44, 72, 19, 0, 0, 0, 0, 0, "Align handles (H Toggles)");
1715                         uiBlockEndAlign(block);
1716                 }
1717                 
1718                 if(totedge==1)
1719                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Crease W:", 10, 30, 290, 19, &(tfp->ve_median[3]), 0.0, 1.0, 10, 3, "");
1720                 else if(totedge>1)
1721                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median Crease W:",  10, 30, 290, 19, &(tfp->ve_median[3]), 0.0, 1.0, 10, 3, "");
1722                 
1723         }
1724         else {  // apply
1725                 memcpy(ve_median, tfp->ve_median, sizeof(tfp->ve_median));
1726                 
1727                 if(G.vd->flag & V3D_GLOBAL_STATS) {
1728                         Mat4Invert(ob->imat, ob->obmat);
1729                         Mat4MulVecfl(ob->imat, median);
1730                         Mat4MulVecfl(ob->imat, ve_median);
1731                 }
1732                 VecSubf(median, ve_median, median);
1733                 median[3]= ve_median[3]-median[3];
1734                 median[4]= ve_median[4]-median[4];
1735                 
1736                 if(ob->type==OB_MESH) {
1737                         
1738                         eve= em->verts.first;
1739                         while(eve) {
1740                                 if(eve->f & SELECT) {
1741                                         VecAddf(eve->co, eve->co, median);
1742                                 }
1743                                 eve= eve->next;
1744                         }
1745                         
1746                         for(eed= em->edges.first; eed; eed= eed->next) {
1747                                 if(eed->f & SELECT) {
1748                                         /* ensure the median can be set to zero or one */
1749                                         if(ve_median[3]==0.0f) eed->crease= 0.0f;
1750                                         else if(ve_median[3]==1.0f) eed->crease= 1.0f;
1751                                         else {
1752                                                 eed->crease+= median[3];
1753                                                 CLAMP(eed->crease, 0.0, 1.0);
1754                                         }
1755                                 }
1756                         }
1757                         
1758                         recalc_editnormals();
1759                 }
1760                 else if(ob->type==OB_CURVE || ob->type==OB_SURF) {
1761                         extern ListBase editNurb; /* editcurve.c */
1762                         Nurb *nu;
1763                         BPoint *bp;
1764                         BezTriple *bezt;
1765                         int a;
1766                         
1767                         nu= editNurb.first;
1768                         while(nu) {
1769                                 if((nu->type & 7)==1) {
1770                                         bezt= nu->bezt;
1771                                         a= nu->pntsu;
1772                                         while(a--) {
1773                                                 if(bezt->f2 & SELECT) {
1774                                                         VecAddf(bezt->vec[0], bezt->vec[0], median);
1775                                                         VecAddf(bezt->vec[1], bezt->vec[1], median);
1776                                                         VecAddf(bezt->vec[2], bezt->vec[2], median);
1777                                                         bezt->weight+= median[4];
1778                                                 }
1779                                                 else {
1780                                                         if(bezt->f1 & SELECT) {
1781                                                                 VecAddf(bezt->vec[0], bezt->vec[0], median);
1782                                                         }
1783                                                         if(bezt->f3 & SELECT) {
1784                                                                 VecAddf(bezt->vec[2], bezt->vec[2], median);
1785                                                         }
1786                                                 }
1787                                                 bezt++;
1788                                         }
1789                                 }
1790                                 else {
1791                                         bp= nu->bp;
1792                                         a= nu->pntsu*nu->pntsv;
1793                                         while(a--) {
1794                                                 if(bp->f1 & SELECT) {
1795                                                         VecAddf(bp->vec, bp->vec, median);
1796                                                         bp->vec[3]+= median[3];
1797                                                         bp->weight+= median[4];
1798                                                 }
1799                                                 bp++;
1800                                         }
1801                                 }
1802                                 test2DNurb(nu);
1803                                 testhandlesNurb(nu); /* test for bezier too */
1804
1805                                 nu= nu->next;
1806                         }
1807                 }
1808                 else if(ob->type==OB_LATTICE) {
1809                         BPoint *bp;
1810                         int a;
1811                         
1812                         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1813                         bp= editLatt->def;
1814                         while(a--) {
1815                                 if(bp->f1 & SELECT) {
1816                                         VecAddf(bp->vec, bp->vec, median);
1817                                         bp->weight+= median[4];
1818                                 }
1819                                 bp++;
1820                         }
1821                 }
1822                 
1823                 BIF_undo_push("Transform properties");
1824         }
1825 }
1826
1827 /* assumes armature active */
1828 static void validate_bonebutton_cb(void *bonev, void *namev)
1829 {
1830         Object *ob= OBACT;
1831         
1832         if(ob && ob->type==OB_ARMATURE) {
1833                 Bone *bone= bonev;
1834                 char oldname[32], newname[32];
1835                 
1836                 /* need to be on the stack */
1837                 BLI_strncpy(newname, bone->name, 32);
1838                 BLI_strncpy(oldname, (char *)namev, 32);
1839                 /* restore */
1840                 BLI_strncpy(bone->name, oldname, 32);
1841                 
1842                 armature_bone_rename(ob->data, oldname, newname); // editarmature.c
1843                 allqueue(REDRAWALL, 0);
1844         }
1845 }
1846
1847 static void v3d_posearmature_buts(uiBlock *block, Object *ob, float lim)
1848 {
1849         uiBut *but;
1850         bArmature *arm;
1851         bPoseChannel *pchan;
1852         Bone *bone= NULL;
1853         TransformProperties *tfp= G.vd->properties_storage;
1854
1855         arm = get_armature(OBACT);
1856         if (!arm || !ob->pose) return;
1857
1858         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1859                 bone = pchan->bone;
1860                 if(bone && (bone->flag & BONE_ACTIVE) && (bone->layer & arm->layer))
1861                         break;
1862         }
1863         if (!pchan || !bone) return;
1864
1865         if((ob->parent) && (ob->partype == PARBONE))
1866                 but= uiDefBut (block, TEX, B_DIFF, "Bone:",                             160, 130, 140, 19, bone->name, 1, 31, 0, 0, "");
1867         else
1868                 but= uiDefBut(block, TEX, B_DIFF, "Bone:",                              160, 140, 140, 19, bone->name, 1, 31, 0, 0, "");
1869         uiButSetFunc(but, validate_bonebutton_cb, bone, NULL);
1870         
1871         QuatToEul(pchan->quat, tfp->ob_eul);
1872         tfp->ob_eul[0]*= 180.0/M_PI;
1873         tfp->ob_eul[1]*= 180.0/M_PI;
1874         tfp->ob_eul[2]*= 180.0/M_PI;
1875         
1876         uiBlockBeginAlign(block);
1877         uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCX, REDRAWVIEW3D, ICON_UNLOCKED,     10,140,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
1878         uiDefButF(block, NUM, B_ARMATUREPANEL2, "LocX:",        30, 140, 120, 19, pchan->loc, -lim, lim, 100, 3, "");
1879         uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCY, REDRAWVIEW3D, ICON_UNLOCKED,     10,120,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
1880         uiDefButF(block, NUM, B_ARMATUREPANEL2, "LocY:",        30, 120, 120, 19, pchan->loc+1, -lim, lim, 100, 3, "");
1881         uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCZ, REDRAWVIEW3D, ICON_UNLOCKED,     10,100,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
1882         uiDefButF(block, NUM, B_ARMATUREPANEL2, "LocZ:",        30, 100, 120, 19, pchan->loc+2, -lim, lim, 100, 3, "");
1883
1884         uiBlockBeginAlign(block);
1885         uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTX, REDRAWVIEW3D, ICON_UNLOCKED,     10,70,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
1886         uiDefButF(block, NUM, B_ARMATUREPANEL3, "RotX:",        30, 70, 120, 19, tfp->ob_eul, -1000.0, 1000.0, 100, 3, "");
1887         uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTY, REDRAWVIEW3D, ICON_UNLOCKED,     10,50,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
1888         uiDefButF(block, NUM, B_ARMATUREPANEL3, "RotY:",        30, 50, 120, 19, tfp->ob_eul+1, -1000.0, 1000.0, 100, 3, "");
1889         uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTZ, REDRAWVIEW3D, ICON_UNLOCKED,     10,30,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
1890         uiDefButF(block, NUM, B_ARMATUREPANEL3, "RotZ:",        30, 30, 120, 19, tfp->ob_eul+2, -1000.0, 1000.0, 100, 3, "");
1891         
1892         uiBlockBeginAlign(block);
1893         uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEX, REDRAWVIEW3D, ICON_UNLOCKED,   160,70,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
1894         uiDefButF(block, NUM, B_ARMATUREPANEL2, "ScaleX:",      180, 70, 120, 19, pchan->size, -lim, lim, 10, 3, "");
1895         uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEY, REDRAWVIEW3D, ICON_UNLOCKED,   160,50,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
1896         uiDefButF(block, NUM, B_ARMATUREPANEL2, "ScaleY:",      180, 50, 120, 19, pchan->size+1, -lim, lim, 10, 3, "");
1897         uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEZ, REDRAWVIEW3D, ICON_UNLOCKED,   160,30,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
1898         uiDefButF(block, NUM, B_ARMATUREPANEL2, "ScaleZ:",      180, 30, 120, 19, pchan->size+2, -lim, lim, 10, 3, "");
1899         uiBlockEndAlign(block);
1900 }
1901
1902 static void v3d_editarmature_buts(uiBlock *block, Object *ob, float lim)
1903 {
1904         bArmature *arm= G.obedit->data;
1905         EditBone *ebone;
1906         uiBut *but;
1907         TransformProperties *tfp= G.vd->properties_storage;
1908         
1909         ebone= G.edbo.first;
1910
1911         for (ebone = G.edbo.first; ebone; ebone=ebone->next){
1912                 if ((ebone->flag & BONE_ACTIVE) && (ebone->layer & arm->layer))
1913                         break;
1914         }
1915
1916         if (!ebone)
1917                 return;
1918         
1919         if((ob->parent) && (ob->partype == PARBONE))
1920                 but= uiDefBut(block, TEX, B_DIFF, "Bone:", 160, 130, 140, 19, ebone->name, 1, 31, 0, 0, "");
1921         else
1922                 but= uiDefBut(block, TEX, B_DIFF, "Bone:",                      160, 150, 140, 19, ebone->name, 1, 31, 0, 0, "");
1923         uiButSetFunc(but, validate_editbonebutton_cb, ebone, NULL);
1924
1925         uiBlockBeginAlign(block);
1926         uiDefButF(block, NUM, B_ARMATUREPANEL1, "HeadX:",       10, 70, 140, 19, ebone->head, -lim, lim, 10, 3, "");
1927         uiDefButF(block, NUM, B_ARMATUREPANEL1, "HeadY:",       10, 50, 140, 19, ebone->head+1, -lim, lim, 10, 3, "");
1928         uiDefButF(block, NUM, B_ARMATUREPANEL1, "HeadZ:",       10, 30, 140, 19, ebone->head+2, -lim, lim, 10, 3, "");
1929         uiBlockBeginAlign(block);
1930         uiDefButF(block, NUM, B_ARMATUREPANEL1, "TailX:",       160, 70, 140, 19, ebone->tail, -lim, lim, 10, 3, "");
1931         uiDefButF(block, NUM, B_ARMATUREPANEL1, "TailY:",       160, 50, 140, 19, ebone->tail+1, -lim, lim, 10, 3, "");
1932         uiDefButF(block, NUM, B_ARMATUREPANEL1, "TailZ:",       160, 30, 140, 19, ebone->tail+2, -lim, lim, 10, 3, "");
1933         uiBlockEndAlign(block);
1934         
1935         tfp->ob_eul[0]= 180.0*ebone->roll/M_PI;
1936         uiDefButF(block, NUM, B_ARMATUREPANEL1, "Roll:",        10, 100, 140, 19, tfp->ob_eul, -lim, lim, 1000, 3, "");
1937
1938         uiDefButBitI(block, TOG, BONE_EDITMODE_LOCKED, REDRAWVIEW3D, "Lock", 160, 100, 140, 19, &(ebone->flag), 0, 0, 0, 0, "Prevents bone from being transformed in edit mode");
1939         
1940         uiBlockBeginAlign(block);
1941         uiDefButF(block, NUM, B_ARMATUREPANEL1, "TailRadius:",  10, 150, 140, 19, &ebone->rad_tail, 0, lim, 10, 3, "");
1942         if (ebone->parent && ebone->flag & BONE_CONNECTED )
1943                 uiDefButF(block, NUM, B_ARMATUREPANEL1, "HeadRadius:",  10, 130, 140, 19, &ebone->parent->rad_tail, 0, lim, 10, 3, "");
1944         else
1945                 uiDefButF(block, NUM, B_ARMATUREPANEL1, "HeadRadius:",  10, 130, 140, 19, &ebone->rad_head, 0, lim, 10, 3, "");
1946         uiBlockEndAlign(block);
1947 }
1948
1949 static void v3d_editmetaball_buts(uiBlock *block, Object *ob, float lim)
1950 {
1951         extern MetaElem *lastelem;
1952
1953         if(lastelem) {
1954                 uiBlockBeginAlign(block);
1955                 uiDefButF(block, NUM, B_RECALCMBALL, "LocX:", 10, 70, 140, 19, &lastelem->x, -lim, lim, 100, 3, "");
1956                 uiDefButF(block, NUM, B_RECALCMBALL, "LocY:", 10, 50, 140, 19, &lastelem->y, -lim, lim, 100, 3, "");
1957                 uiDefButF(block, NUM, B_RECALCMBALL, "LocZ:", 10, 30, 140, 19, &lastelem->z, -lim, lim, 100, 3, "");
1958
1959                 uiBlockBeginAlign(block);
1960                 if(lastelem->type!=MB_BALL)
1961                         uiDefButF(block, NUM, B_RECALCMBALL, "dx:", 160, 70, 140, 19, &lastelem->expx, 0, lim, 100, 3, "");
1962                 if((lastelem->type!=MB_BALL) && (lastelem->type!=MB_TUBE))
1963                         uiDefButF(block, NUM, B_RECALCMBALL, "dy:", 160, 50, 140, 19, &lastelem->expy, 0, lim, 100, 3, "");
1964                 if((lastelem->type==MB_ELIPSOID) || (lastelem->type==MB_CUBE))
1965                         uiDefButF(block, NUM, B_RECALCMBALL, "dz:", 160, 30, 140, 19, &lastelem->expz, 0, lim, 100, 3, "");
1966
1967                 uiBlockEndAlign(block); 
1968
1969                 uiBlockBeginAlign(block);
1970                 uiDefButF(block, NUM, B_RECALCMBALL, "Radius:", 10, 120, 140, 19, &lastelem->rad, 0, lim, 100, 3, "Size of the active metaball");
1971                 uiDefButF(block, NUM, B_RECALCMBALL, "Stiffness:", 10, 100, 140, 19, &lastelem->s, 0, 10, 100, 3, "Stiffness of the active metaball");
1972                 uiBlockEndAlign(block);
1973                 
1974                 uiDefButS(block, MENU, B_RECALCMBALL, "Type%t|Ball%x0|Tube%x4|Plane%x5|Elipsoid%x6|Cube%x7", 160, 120, 140, 19, &lastelem->type, 0.0, 0.0, 0, 0, "Set active element type");
1975                 
1976         }
1977 }
1978
1979 void do_viewbuts(unsigned short event)
1980 {
1981         BoundBox *bb;
1982         View3D *vd;
1983         Object *ob= OBACT;
1984         TransformProperties *tfp= G.vd->properties_storage;
1985         
1986         vd= G.vd;
1987         if(vd==NULL) return;
1988
1989         switch(event) {
1990                 
1991         case B_OBJECTPANEL:
1992                 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
1993                 allqueue(REDRAWVIEW3D, 1);
1994                 break;
1995                 
1996         case B_OBJECTPANELROT:
1997                 if(ob) {
1998                         ob->rot[0]= M_PI*tfp->ob_eul[0]/180.0;
1999                         ob->rot[1]= M_PI*tfp->ob_eul[1]/180.0;
2000                         ob->rot[2]= M_PI*tfp->ob_eul[2]/180.0;
2001                         DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
2002                         allqueue(REDRAWVIEW3D, 1);
2003                 }
2004                 break;
2005
2006         case B_OBJECTPANELSCALE:
2007                 if(ob) {
2008
2009                         /* link scale; figure out which axis changed */
2010                         if (tfp->link_scale) {
2011                                 float ratio, tmp, max = 0.0;
2012                                 int axis;
2013                                 
2014                                 axis = 0;
2015                                 max = fabs(tfp->ob_scale[0] - ob->size[0]);
2016                                 tmp = fabs(tfp->ob_scale[1] - ob->size[1]);
2017                                 if (tmp > max) {
2018                                         axis = 1;
2019                                         max = tmp;
2020                                 }
2021                                 tmp = fabs(tfp->ob_scale[2] - ob->size[2]);
2022                                 if (tmp > max) {
2023                                         axis = 2;
2024                                         max = tmp;
2025                                 }
2026                         
2027                                 if (ob->size[axis] != tfp->ob_scale[axis]) {
2028                                         if (fabs(ob->size[axis]) > FLT_EPSILON) {
2029                                                 ratio = tfp->ob_scale[axis] / ob->size[axis];
2030                                                 ob->size[0] *= ratio;
2031                                                 ob->size[1] *= ratio;
2032                                                 ob->size[2] *= ratio;
2033                                         }
2034                                 }
2035                         }
2036                         else {
2037                                 VECCOPY(ob->size, tfp->ob_scale);
2038                                 
2039                         }
2040                         DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
2041                         allqueue(REDRAWVIEW3D, 1);
2042                 }
2043                 break;
2044
2045         case B_OBJECTPANELDIMS:
2046                 bb= object_get_boundbox(ob);
2047                 if(bb) {
2048                         float old_dims[3], scale[3], ratio, len[3];
2049                         int axis;
2050
2051                         Mat4ToSize(ob->obmat, scale);
2052
2053                         len[0] = bb->vec[4][0] - bb->vec[0][0];
2054                         len[1] = bb->vec[2][1] - bb->vec[0][1];
2055                         len[2] = bb->vec[1][2] - bb->vec[0][2];
2056
2057                         old_dims[0] = fabs(scale[0]) * len[0];
2058                         old_dims[1] = fabs(scale[1]) * len[1];
2059                         old_dims[2] = fabs(scale[2]) * len[2];
2060
2061                         /* for each axis changed */
2062                         for (axis = 0; axis<3; axis++) {
2063                                 if (fabs(old_dims[axis] - tfp->ob_dims[axis]) > 0.0001) {
2064                                         if (old_dims[axis] > 0.0) {
2065                                                 ratio = tfp->ob_dims[axis] / old_dims[axis]; 
2066                                                 if (tfp->link_scale) {
2067                                                         ob->size[0] *= ratio;
2068                                                         ob->size[1] *= ratio;
2069                                                         ob->size[2] *= ratio;
2070                                                         break;
2071                                                 }
2072                                                 else {
2073                                                         ob->size[axis] *= ratio;
2074                                                 }
2075                                         }
2076                                         else {
2077                                                 if (len[axis] > 0) {
2078                                                         ob->size[axis] = tfp->ob_dims[axis] / len[axis];
2079                                                 }
2080                                         }
2081                                 }
2082                         }
2083                         
2084                         /* prevent multiple B_OBJECTPANELDIMS events to keep scaling, cycling with TAB on buttons can cause that */
2085                         VECCOPY(tfp->ob_dims, old_dims);
2086                         
2087                         DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
2088                         allqueue(REDRAWVIEW3D, 1);
2089                 }
2090                 break;
2091         
2092         case B_OBJECTPANELMEDIAN:
2093                 if(ob) {
2094                         v3d_editvertex_buts(NULL, ob, 1.0);
2095                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2096                         allqueue(REDRAWVIEW3D, 1);
2097                 }
2098                 break;
2099                 
2100                 /* note; this case also used for parbone */
2101         case B_OBJECTPANELPARENT:
2102                 if(ob) {
2103                         if(ob->id.lib || test_parent_loop(ob->parent, ob) ) 
2104                                 ob->parent= NULL;
2105                         else {
2106                                 DAG_scene_sort(G.scene);
2107                                 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
2108                         }
2109                         allqueue(REDRAWVIEW3D, 1);
2110                         allqueue(REDRAWBUTSOBJECT, 0);
2111                         allqueue(REDRAWOOPS, 0);
2112                 }
2113                 break;
2114                 
2115         case B_ARMATUREPANEL1:
2116                 {
2117                         bArmature *arm= G.obedit->data;
2118                         EditBone *ebone, *child;
2119                         
2120                         for (ebone = G.edbo.first; ebone; ebone=ebone->next){
2121                                 if ((ebone->flag & BONE_ACTIVE) && (ebone->layer & arm->layer))
2122                                         break;
2123                         }
2124                         if (ebone) {
2125                                 ebone->roll= M_PI*tfp->ob_eul[0]/180.0;
2126                                 //      Update our parent
2127                                 if (ebone->parent && ebone->flag & BONE_CONNECTED){
2128                                         VECCOPY (ebone->parent->tail, ebone->head);
2129                                 }
2130                         
2131                                 //      Update our children if necessary
2132                                 for (child = G.edbo.first; child; child=child->next){
2133                                         if (child->parent == ebone && (child->flag & BONE_CONNECTED)){
2134                                                 VECCOPY (child->head, ebone->tail);
2135                                         }
2136                                 }
2137                                 if(arm->flag & ARM_MIRROR_EDIT) {
2138                                         EditBone *eboflip= armature_bone_get_mirrored(ebone);
2139                                         if(eboflip) {
2140                                                 eboflip->roll= -ebone->roll;
2141                                                 eboflip->head[0]= -ebone->head[0];
2142                                                 eboflip->tail[0]= -ebone->tail[0];
2143                                                 
2144                                                 //      Update our parent
2145                                                 if (eboflip->parent && eboflip->flag & BONE_CONNECTED){
2146                                                         VECCOPY (eboflip->parent->tail, eboflip->head);
2147                                                 }
2148                                                 
2149                                                 //      Update our children if necessary
2150                                                 for (child = G.edbo.first; child; child=child->next){
2151                                                         if (child->parent == eboflip && (child->flag & BONE_CONNECTED)){
2152                                                                 VECCOPY (child->head, eboflip->tail);
2153                                                         }
2154                                                 }
2155                                         }
2156                                 }
2157                                 
2158                                 allqueue(REDRAWVIEW3D, 1);
2159                         }
2160                 }
2161                 break;
2162         case B_ARMATUREPANEL3:  // rotate button on channel
2163                 {
2164                         bArmature *arm;
2165                         bPoseChannel *pchan;
2166                         Bone *bone;
2167                         float eul[3];
2168                         
2169                         arm = get_armature(OBACT);
2170                         if (!arm || !ob->pose) return;
2171                                 
2172                         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
2173                                 bone = pchan->bone;
2174                                 if(bone && (bone->flag & BONE_ACTIVE) && (bone->layer & arm->layer))
2175                                         break;
2176                         }
2177                         if (!pchan) return;
2178                         
2179                         /* make a copy to eul[3], to allow TAB on buttons to work */
2180                         eul[0]= M_PI*tfp->ob_eul[0]/180.0;
2181                         eul[1]= M_PI*tfp->ob_eul[1]/180.0;
2182                         eul[2]= M_PI*tfp->ob_eul[2]/180.0;
2183                         EulToQuat(eul, pchan->quat);
2184                 }
2185                 /* no break, pass on */
2186         case B_ARMATUREPANEL2:
2187                 {
2188                         ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
2189                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2190                         allqueue(REDRAWVIEW3D, 1);
2191                 }
2192                 break;
2193         case B_TRANSFORMSPACEADD:
2194                 BIF_manageTransformOrientation(1, 0);
2195                 allqueue(REDRAWVIEW3D, 1);
2196                 break;
2197         case B_TRANSFORMSPACECLEAR:
2198                 BIF_clearTransformOrientation();
2199                 allqueue(REDRAWVIEW3D, 1);
2200         }
2201 }
2202
2203 void removeTransformOrientation_func(void *target, void *unused)
2204 {
2205         BIF_removeTransformOrientation((TransformOrientation *) target);
2206 }
2207
2208 void selectTransformOrientation_func(void *target, void *unused)
2209 {
2210         BIF_selectTransformOrientation((TransformOrientation *) target);
2211 }
2212
2213 static void view3d_panel_transform_spaces(short cntrl)
2214 {
2215         ListBase *transform_spaces = &G.scene->transform_spaces;
2216         TransformOrientation *ts = transform_spaces->first;
2217         uiBlock *block;
2218         uiBut *but;
2219         int xco = 20, yco = 70, height = 140;
2220         int index;
2221
2222         block= uiNewBlock(&curarea->uiblocks, "view3d_panel_transform", UI_EMBOSS, UI_HELV, curarea->win);
2223         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE  | cntrl);
2224         uiSetPanelHandler(VIEW3D_HANDLER_TRANSFORM);  // for close and esc
2225
2226         if(uiNewPanel(curarea, block, "Transform Orientations", "View3d", 10, 230, 318, height)==0) return;
2227
2228         uiNewPanelHeight(block, height);
2229
2230         uiBlockBeginAlign(block);
2231         
2232         if (G.obedit)
2233                 uiDefBut(block, BUT, B_TRANSFORMSPACEADD, "Add", xco,120,80,20, 0, 0, 0, 0, 0, "Add the selected element as a Transform Orientation");
2234         else
2235                 uiDefBut(block, BUT, B_TRANSFORMSPACEADD, "Add", xco,120,80,20, 0, 0, 0, 0, 0, "Add the active object as a Transform Orientation");
2236
2237         uiDefBut(block, BUT, B_TRANSFORMSPACECLEAR, "Clear", xco + 80,120,80,20, 0, 0, 0, 0, 0, "Removal all Transform Orientations");
2238         
2239         uiBlockEndAlign(block);
2240         
2241         uiBlockBeginAlign(block);
2242         
2243         uiDefButS(block, ROW, REDRAWHEADERS, "Global",  xco,            90, 40,20, &G.vd->twmode, 5.0, (float)V3D_MANIP_GLOBAL,0, 0, "Global Transform Orientation");
2244         uiDefButS(block, ROW, REDRAWHEADERS, "Local",   xco + 40,       90, 40,20, &G.vd->twmode, 5.0, (float)V3D_MANIP_LOCAL, 0, 0, "Local Transform Orientation");
2245         uiDefButS(block, ROW, REDRAWHEADERS, "Normal",  xco + 80,       90, 40,20, &G.vd->twmode, 5.0, (float)V3D_MANIP_NORMAL,0, 0, "Normal Transform Orientation");
2246         uiDefButS(block, ROW, REDRAWHEADERS, "View",            xco + 120,      90, 40,20, &G.vd->twmode, 5.0, (float)V3D_MANIP_VIEW,   0, 0, "View Transform Orientation");
2247         
2248         for (index = V3D_MANIP_CUSTOM, ts = transform_spaces->first ; ts ; ts = ts->next, index++) {
2249
2250                 BIF_ThemeColor(TH_BUT_ACTION);
2251                 if (G.vd->twmode == index) {
2252                         but = uiDefIconButS(block,ROW, REDRAWHEADERS, ICON_CHECKBOX_HLT, xco,yco,XIC,YIC, &G.vd->twmode, 5.0, (float)index, 0, 0, "Use this Custom Transform Orientation");
2253                 }
2254                 else {
2255                         but = uiDefIconButS(block,ROW, REDRAWHEADERS, ICON_CHECKBOX_DEHLT, xco,yco,XIC,YIC, &G.vd->twmode, 5.0, (float)index, 0, 0, "Use this Custom Transform Orientation");
2256                 }
2257                 uiButSetFunc(but, selectTransformOrientation_func, ts, NULL);
2258                 uiDefBut(block, TEX, 0, "", xco+=XIC, yco,100+XIC,20, &ts->name, 0, 30, 0, 0, "Edits the name of this Transform Orientation");
2259                 but = uiDefIconBut(block, BUT, REDRAWVIEW3D, ICON_X, xco+=100+XIC,yco,XIC,YIC, 0, 0, 0, 0, 0, "Deletes this Transform Orientation");
2260                 uiButSetFunc(but, removeTransformOrientation_func, ts, NULL);
2261
2262                 xco = 20;
2263                 yco -= 25;
2264         }
2265         uiBlockEndAlign(block);
2266         
2267         if(yco < 0) uiNewPanelHeight(block, height-yco);
2268 }
2269
2270
2271 static void view3d_panel_object(short cntrl)    // VIEW3D_HANDLER_OBJECT
2272 {
2273         uiBlock *block;
2274         uiBut *bt;
2275         Object *ob= OBACT;
2276         TransformProperties *tfp;
2277         float lim;
2278         static char hexcol[128];
2279         
2280         if(ob==NULL) return;
2281
2282         /* make sure we got storage */
2283         if(G.vd->properties_storage==NULL)
2284                 G.vd->properties_storage= MEM_callocN(sizeof(TransformProperties), "TransformProperties");
2285         tfp= G.vd->properties_storage;
2286         
2287         block= uiNewBlock(&curarea->uiblocks, "view3d_panel_object", UI_EMBOSS, UI_HELV, curarea->win);
2288         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
2289         uiSetPanelHandler(VIEW3D_HANDLER_OBJECT);  // for close and esc
2290
2291         if((G.f & G_SCULPTMODE) && !G.obedit) {
2292                 if(!uiNewPanel(curarea, block, "Transform Properties", "View3d", 10, 230, 318, 234))
2293                         return;
2294         } else if(G.f & G_PARTICLEEDIT && !G.obedit){
2295                 if(!uiNewPanel(curarea, block, "Transform Properties", "View3d", 10, 230, 318, 234))
2296                         return;
2297         } else {
2298                 if(!uiNewPanel(curarea, block, "Transform Properties", "View3d", 10, 230, 318, 204))
2299                         return;
2300         }
2301
2302         uiSetButLock(object_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2303         
2304         if(G.f & (G_VERTEXPAINT|G_TEXTUREPAINT|G_WEIGHTPAINT)) {
2305                 uiBlockSetFlag(block, UI_BLOCK_FRONTBUFFER);    // force old style frontbuffer draw
2306         }
2307         else {
2308                 bt= uiDefBut(block, TEX, B_IDNAME, "OB: ",      10,180,140,20, ob->id.name+2, 0.0, 21.0, 0, 0, "");
2309 #ifdef WITH_VERSE
2310                 if(ob->vnode) uiButSetFunc(bt, test_and_send_idbutton_cb, ob, ob->id.name);
2311                 else uiButSetFunc(bt, test_idbutton_cb, ob->id.name, NULL);
2312 #else
2313                 uiButSetFunc(bt, test_idbutton_cb, ob->id.name, NULL);
2314 #endif
2315
2316                 if((G.f & G_PARTICLEEDIT)==0) {
2317                         uiBlockBeginAlign(block);
2318                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_OBJECTPANELPARENT, "Par:", 160, 180, 140, 20, &ob->parent, "Parent Object"); 
2319                         if((ob->parent) && (ob->partype == PARBONE)) {
2320                                 bt= uiDefBut(block, TEX, B_OBJECTPANELPARENT, "ParBone:", 160, 160, 140, 20, ob->parsubstr, 0, 30, 0, 0, "");
2321                                 uiButSetCompleteFunc(bt, autocomplete_bone, (void *)ob->parent);
2322                         }
2323                         else {
2324                                 strcpy(ob->parsubstr, "");
2325                         }
2326                         uiBlockEndAlign(block);
2327                 }
2328         }
2329
2330         lim= 10000.0f*MAX2(1.0, G.vd->grid);
2331
2332         if(ob==G.obedit) {
2333                 if(ob->type==OB_ARMATURE) v3d_editarmature_buts(block, ob, lim);
2334                 if(ob->type==OB_MBALL) v3d_editmetaball_buts(block, ob, lim);
2335                 else v3d_editvertex_buts(block, ob, lim);
2336         }
2337         else if(ob->flag & OB_POSEMODE) {
2338                 v3d_posearmature_buts(block, ob, lim);
2339         }
2340         else if(G.f & G_WEIGHTPAINT) {
2341                 uiNewPanelTitle(block, "Weight Paint Properties");
2342                 weight_paint_buttons(block);
2343         }
2344         else if(G.f & (G_VERTEXPAINT|G_TEXTUREPAINT)) {
2345                 extern VPaint Gvp;         /* from vpaint */
2346                 static float hsv[3], old[3];    // used as temp mem for picker
2347                 float *rgb= NULL;
2348                 ToolSettings *settings= G.scene->toolsettings;
2349
2350                 if(G.f & G_VERTEXPAINT) rgb= &Gvp.r;
2351                 else if(settings->imapaint.brush) rgb= settings->imapaint.brush->rgb;
2352                 
2353                 uiNewPanelTitle(block, "Paint Properties");
2354                 if (rgb)
2355                         /* 'f' is for floating panel */
2356                         uiBlockPickerButtons(block, rgb, hsv, old, hexcol, 'f', REDRAWBUTSEDIT);
2357         }
2358         else if(G.f & G_SCULPTMODE) {
2359                 uiNewPanelTitle(block, "Sculpt Properties");
2360                 sculptmode_draw_interface_tools(block,10,150);
2361         } else if(G.f & G_PARTICLEEDIT){
2362                 uiNewPanelTitle(block, "Particle Edit Properties");
2363                 particle_edit_buttons(block);
2364         } else {
2365                 BoundBox *bb = NULL;
2366
2367                 uiBlockBeginAlign(block);
2368                 uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCX, REDRAWVIEW3D, ICON_UNLOCKED,     10,150,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
2369                 uiDefButF(block, NUM, B_OBJECTPANEL, "LocX:",           30, 150, 120, 19, &(ob->loc[0]), -lim, lim, 100, 3, "");
2370                 uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCY, REDRAWVIEW3D, ICON_UNLOCKED,     10,130,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
2371                 uiDefButF(block, NUM, B_OBJECTPANEL, "LocY:",           30, 130, 120, 19, &(ob->loc[1]), -lim, lim, 100, 3, "");
2372                 uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCZ, REDRAWVIEW3D, ICON_UNLOCKED,     10,110,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
2373                 uiDefButF(block, NUM, B_OBJECTPANEL, "LocZ:",           30, 110, 120, 19, &(ob->loc[2]), -lim, lim, 100, 3, "");
2374                 
2375                 tfp->ob_eul[0]= 180.0*ob->rot[0]/M_PI;
2376                 tfp->ob_eul[1]= 180.0*ob->rot[1]/M_PI;
2377                 tfp->ob_eul[2]= 180.0*ob->rot[2]/M_PI;
2378                 
2379                 uiBlockBeginAlign(block);
2380                 if ((ob->parent) && (ob->partype == PARBONE)) {
2381                         uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTX, REDRAWVIEW3D, ICON_UNLOCKED,     160,130,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
2382                         uiDefButF(block, NUM, B_OBJECTPANELROT, "RotX:",        180, 130, 120, 19, &(tfp->ob_eul[0]), -lim, lim, 1000, 3, "");
2383                         uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTY, REDRAWVIEW3D, ICON_UNLOCKED,     160,110,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
2384                         uiDefButF(block, NUM, B_OBJECTPANELROT, "RotY:",        180, 110, 120, 19, &(tfp->ob_eul[1]), -lim, lim, 1000, 3, "");
2385                         uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTZ, REDRAWVIEW3D, ICON_UNLOCKED,     160,90,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
2386                         uiDefButF(block, NUM, B_OBJECTPANELROT, "RotZ:",        180, 90, 120, 19, &(tfp->ob_eul[2]), -lim, lim, 1000, 3, "");
2387
2388                 }
2389                 else {
2390                         uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTX, REDRAWVIEW3D, ICON_UNLOCKED,     160,150,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
2391                         uiDefButF(block, NUM, B_OBJECTPANELROT, "RotX:",        180, 150, 120, 19, &(tfp->ob_eul[0]), -lim, lim, 1000, 3, "");
2392                         uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTY, REDRAWVIEW3D, ICON_UNLOCKED,     160,130,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
2393                         uiDefButF(block, NUM, B_OBJECTPANELROT, "RotY:",        180, 130, 120, 19, &(tfp->ob_eul[1]), -lim, lim, 1000, 3, "");
2394                         uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTZ, REDRAWVIEW3D, ICON_UNLOCKED,     160,110,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
2395                         uiDefButF(block, NUM, B_OBJECTPANELROT, "RotZ:",        180, 110, 120, 19, &(tfp->ob_eul[2]), -lim, lim, 1000, 3, "");
2396                 }
2397
2398                 tfp->ob_scale[0]= ob->size[0];
2399                 tfp->ob_scale[1]= ob->size[1];
2400                 tfp->ob_scale[2]= ob->size[2];
2401
2402                 uiBlockBeginAlign(block);
2403                 uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEX, REDRAWVIEW3D, ICON_UNLOCKED,   10,80,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
2404                 uiDefButF(block, NUM, B_OBJECTPANELSCALE, "ScaleX:",            30, 80, 120, 19, &(tfp->ob_scale[0]), -lim, lim, 10, 3, "");
2405                 uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEY, REDRAWVIEW3D, ICON_UNLOCKED,   10,60,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
2406                 uiDefButF(block, NUM, B_OBJECTPANELSCALE, "ScaleY:",            30, 60, 120, 19, &(tfp->ob_scale[1]), -lim, lim, 10, 3, "");
2407                 uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEZ, REDRAWVIEW3D, ICON_UNLOCKED,   10,40,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed");
2408                 uiDefButF(block, NUM, B_OBJECTPANELSCALE, "ScaleZ:",            30, 40, 120, 19, &(tfp->ob_scale[2]), -lim, lim, 10, 3, "");
2409                 uiBlockEndAlign(block);
2410                 
2411                 uiDefButS(block, TOG, REDRAWVIEW3D, "Link Scale",               10, 10, 140, 19, &(tfp->link_scale), 0, 1, 0, 0, "Scale values vary proportionally in all directions");
2412
2413                 bb= object_get_boundbox(ob);
2414                 if (bb) {
2415                         float scale[3];
2416
2417                         Mat4ToSize(ob->obmat, scale);
2418
2419                         tfp->ob_dims[0] = fabs(scale[0]) * (bb->vec[4][0] - bb->vec[0][0]);
2420                         tfp->ob_dims[1] = fabs(scale[1]) * (bb->vec[2][1] - bb->vec[0][1]);
2421                         tfp->ob_dims[2] = fabs(scale[2]) * (bb->vec[1][2] - bb->vec[0][2]);
2422
2423                         uiBlockBeginAlign(block);
2424                         if ((ob->parent) && (ob->partype == PARBONE)) {
2425                                 uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimX:",               160, 60, 140, 19, &(tfp->ob_dims[0]), 0.0, lim, 10, 3, "Manipulate bounding box size");
2426                                 uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimY:",               160, 40, 140, 19, &(tfp->ob_dims[1]), 0.0, lim, 10, 3, "Manipulate bounding box size");
2427                                 uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimZ:",               160, 20, 140, 19, &(tfp->ob_dims[2]), 0.0, lim, 10, 3, "Manipulate bounding box size");
2428
2429                         }
2430                         else {
2431                                 uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimX:",               160, 80, 140, 19, &(tfp->ob_dims[0]), 0.0, lim, 10, 3, "Manipulate bounding box size");
2432                                 uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimY:",               160, 60, 140, 19, &(tfp->ob_dims[1]), 0.0, lim, 10, 3, "Manipulate bounding box size");
2433                                 uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimZ:",               160, 40, 140, 19, &(tfp->ob_dims[2]), 0.0, lim, 10, 3, "Manipulate bounding box size");
2434                         }
2435
2436                         uiBlockEndAlign(block);
2437                 }
2438         }
2439         uiClearButLock();
2440 }
2441
2442 static void view3d_panel_background(short cntrl)        // VIEW3D_HANDLER_BACKGROUND
2443 {
2444         uiBlock *block;
2445         View3D *vd;
2446         
2447         vd= G.vd;
2448
2449         block= uiNewBlock(&curarea->uiblocks, "view3d_panel_background", UI_EMBOSS, UI_HELV, curarea->win);
2450         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE  | cntrl);
2451         uiSetPanelHandler(VIEW3D_HANDLER_BACKGROUND);  // for close and esc
2452         if(uiNewPanel(curarea, block, "Background Image", "View3d", 340, 10, 318, 204)==0) return;
2453
2454         if(G.f & G_VERTEXPAINT || G.f & G_WEIGHTPAINT || G.f & G_TEXTUREPAINT || G.f & G_GREASEPENCIL) {
2455                 uiBlockSetFlag(block, UI_BLOCK_FRONTBUFFER);    // force old style frontbuffer draw
2456         }
2457         
2458         if(vd->flag & V3D_DISPBGPIC) {
2459                 if(vd->bgpic==NULL) {
2460                         vd->bgpic= MEM_callocN(sizeof(BGpic), "bgpic");
2461                         vd->bgpic->size= 5.0;
2462                         vd->bgpic->blend= 0.5;
2463                         vd->bgpic->iuser.fie_ima= 2;
2464                         vd->bgpic->iuser.ok= 1;
2465                 }
2466         }
2467         
2468         if(!(vd->flag & V3D_DISPBGPIC)) {
2469                 uiDefButBitS(block, TOG, V3D_DISPBGPIC, B_REDR, "Use Background Image", 10, 180, 150, 20, &vd->flag, 0, 0, 0, 0, "Display an image in the background of this 3D View");
2470                 uiDefBut(block, LABEL, 1, " ",  160, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
2471         }
2472         else {
2473                 uiBlockBeginAlign(block);
2474                 uiDefButBitS(block, TOG, V3D_DISPBGPIC, B_REDR, "Use", 10, 225, 50, 20, &vd->flag, 0, 0, 0, 0, "Display an image in the background of this 3D View");
2475                 uiDefButF(block, NUMSLI, B_REDR, "Blend:",      60, 225, 150, 20, &vd->bgpic->blend, 0.0,1.0, 0, 0, "Set the transparency of the background image");
2476                 uiDefButF(block, NUM, B_REDR, "Size:",          210, 225, 100, 20, &vd->bgpic->size, 0.1, 250.0*vd->grid, 100, 0, "Set the size (width) of the background image");
2477
2478                 uiDefButF(block, NUM, B_REDR, "X Offset:",      10, 205, 150, 20, &vd->bgpic->xof, -250.0*vd->grid,250.0*vd->grid, 10, 2, "Set the horizontal offset of the background image");
2479                 uiDefButF(block, NUM, B_REDR, "Y Offset:",      160, 205, 150, 20, &vd->bgpic->yof, -250.0*vd->grid,250.0*vd->grid, 10, 2, "Set the vertical offset of the background image");
2480                 
2481                 uiblock_image_panel(block, &vd->bgpic->ima, &vd->bgpic->iuser, B_REDR, B_REDR);
2482         }
2483 }
2484
2485
2486 static void view3d_panel_properties(short cntrl)        // VIEW3D_HANDLER_SETTINGS
2487 {
2488         uiBlock *block;
2489         View3D *vd;
2490         float *curs;
2491         
2492         vd= G.vd;
2493
2494         block= uiNewBlock(&curarea->uiblocks, "view3d_panel_properties", UI_EMBOSS, UI_HELV, curarea->win);
2495         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE  | cntrl);
2496         uiSetPanelHandler(VIEW3D_HANDLER_PROPERTIES);  // for close and esc
2497         if(uiNewPanel(curarea, block, "View Properties", "View3d", 340, 30, 318, 254)==0) return;
2498
2499         /* to force height */
2500         uiNewPanelHeight(block, 264);
2501
2502         if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT|G_GREASEPENCIL)) {
2503                 uiBlockSetFlag(block, UI_BLOCK_FRONTBUFFER);    // force old style frontbuffer draw
2504         }
2505
2506         uiDefBut(block, LABEL, 1, "Grid:",                                      10, 220, 150, 19, NULL, 0.0, 0.0, 0, 0, "");
2507         uiBlockBeginAlign(block);
2508         uiDefButF(block, NUM, REDRAWVIEW3D, "Spacing:",         10, 200, 140, 19, &vd->grid, 0.001, 100.0, 10, 0, "Set the distance between grid lines");
2509         uiDefButS(block, NUM, REDRAWVIEW3D, "Lines:",           10, 180, 140, 19, &vd->gridlines, 0.0, 100.0, 100, 0, "Set the number of grid lines in perspective view");
2510         uiDefButS(block, NUM, REDRAWVIEW3D, "Divisions:",               10, 160, 140, 19, &vd->gridsubdiv, 1.0, 100.0, 100, 0, "Set the number of grid lines");
2511         uiBlockEndAlign(block);
2512
2513         uiDefBut(block, LABEL, 1, "3D Display:",                                                        160, 220, 150, 19, NULL, 0.0, 0.0, 0, 0, "");
2514         uiDefButBitS(block, TOG, V3D_SHOW_FLOOR, REDRAWVIEW3D, "Grid Floor",160, 200, 150, 19, &vd->gridflag, 0, 0, 0, 0, "Show the grid floor in free camera mode");
2515         uiDefButBitS(block, TOG, V3D_SHOW_X, REDRAWVIEW3D, "X Axis",            160, 176, 48, 19, &vd->gridflag, 0, 0, 0, 0, "Show the X Axis line");
2516         uiDefButBitS(block, TOG, V3D_SHOW_Y, REDRAWVIEW3D, "Y Axis",            212, 176, 48, 19, &vd->gridflag, 0, 0, 0, 0, "Show the Y Axis line");
2517         uiDefButBitS(block, TOG, V3D_SHOW_Z, REDRAWVIEW3D, "Z Axis",            262, 176, 48, 19, &vd->gridflag, 0, 0, 0, 0, "Show the Z Axis line");
2518
2519         uiDefBut(block, LABEL, 1, "View Camera:",                       10, 140, 140, 19, NULL, 0.0, 0.0, 0, 0, "");
2520         
2521         uiDefButF(block, NUM, REDRAWVIEW3D, "Lens:",            10, 120, 140, 19, &vd->lens, 10.0, 120.0, 100, 0, "The lens angle in perspective view");
2522         uiBlockBeginAlign(block);
2523         uiDefButF(block, NUM, REDRAWVIEW3D, "Clip Start:",      10, 96, 140, 19, &vd->near, vd->grid/100.0, 100.0, 10, 0, "Set the beginning of the range in which 3D objects are displayed (perspective view)");
2524         uiDefButF(block, NUM, REDRAWVIEW3D, "Clip End:",        10, 76, 140, 19, &vd->far, 1.0, 10000.0*vd->grid, 100, 0, "Set the end of the range in which 3D objects are displayed (perspective view)");
2525         uiBlockEndAlign(block);
2526
2527         uiDefBut(block, LABEL, 1, "3D Cursor:",                         160, 150, 140, 19, NULL, 0.0, 0.0, 0, 0, "");
2528
2529         uiBlockBeginAlign(block);
2530         curs= give_cursor();
2531         uiDefButF(block, NUM, REDRAWVIEW3D, "X:",                       160, 130, 150, 22, curs, -10000.0*vd->grid, 10000.0*vd->grid, 10, 0, "X co-ordinate of the 3D cursor");
2532         uiDefButF(block, NUM, REDRAWVIEW3D, "Y:",                       160, 108, 150, 22, curs+1, -10000.0*vd->grid, 10000.0*vd->grid, 10, 0, "Y co-ordinate of the 3D cursor");
2533         uiDefButF(block, NUM, REDRAWVIEW3D, "Z:",                       160, 86, 150, 22, curs+2, -10000.0*vd->grid, 10000.0*vd->grid, 10, 0, "Z co-ordinate of the 3D cursor");
2534         uiBlockEndAlign(block);
2535
2536         uiDefBut(block, LABEL, 1, "Display:",                           10, 50, 150, 19, NULL, 0.0, 0.0, 0, 0, "");
2537         uiBlockBeginAlign(block);
2538         uiDefButBitS(block, TOG, V3D_SELECT_OUTLINE, REDRAWVIEW3D, "Outline Selected", 10, 30, 140, 19, &vd->flag, 0, 0, 0, 0, "Highlight selected objects with an outline, in Solid, Shaded or Textured viewport shading modes");
2539         uiDefButBitS(block, TOG, V3D_DRAW_CENTERS, REDRAWVIEW3D, "All Object Centers", 10, 10, 140, 19, &vd->flag, 0, 0, 0, 0, "Draw the center points on all objects");
2540         uiDefButBitS(block, TOGN, V3D_HIDE_HELPLINES, REDRAWVIEW3D, "Relationship Lines", 10, -10, 140, 19, &vd->flag, 0, 0, 0, 0, "Draw dashed lines indicating Parent, Constraint, or Hook relationships");
2541         uiDefButBitS(block, TOG, V3D_SOLID_TEX, REDRAWVIEW3D, "Solid Tex", 10, -30, 140, 19, &vd->flag2, 0, 0, 0, 0, "Display textures in Solid draw type (Shift T)");
2542         uiBlockEndAlign(block);
2543
2544         uiDefBut(block, LABEL, 1, "View Locking:",                              160, 60, 150, 19, NULL, 0.0, 0.0, 0, 0, "");
2545         uiBlockBeginAlign(block);
2546         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, REDRAWVIEW3D, "Object:", 160, 40, 140, 19, &vd->ob_centre, "Lock view to center to this Object"); 
2547         uiDefBut(block, TEX, REDRAWVIEW3D, "Bone:",                                             160, 20, 140, 19, vd->ob_centre_bone, 1, 31, 0, 0, "If view locked to Object, use this Bone to lock to view to");
2548
2549         uiDefBut(block, LABEL, 1, "Keyframe Display:",                          160, -2, 150, 19, NULL, 0.0, 0.0, 0, 0, "");
2550         uiBlockBeginAlign(block);
2551         uiDefButBitS(block, TOG, ANIMFILTER_ACTIVE, REDRAWVIEW3D, "Active",160, -22, 50, 19, &vd->keyflags, 0, 0, 0, 0, "Show keyframes for active element only (i.e. active bone or active material)");
2552         uiDefButBitS(block, TOG, ANIMFILTER_MUTED, REDRAWVIEW3D, "Muted",210, -22, 50, 19, &vd->keyflags, 0, 0, 0, 0, "Show keyframes in muted channels");
2553         uiDefButBitS(block, TOG, ANIMFILTER_LOCAL, REDRAWVIEW3D, "Local",260, -22, 50, 19, &vd->keyflags, 0, 0, 0, 0, "Show keyframes directly connected to datablock");
2554         if ((vd->keyflags & ANIMFILTER_LOCAL)==0) {
2555                 uiDefButBitS(block, TOGN, ANIMFILTER_NOMAT, REDRAWVIEW3D, "Material",160, -42, 75, 19, &vd->keyflags, 0, 0, 0, 0, "Show keyframes for any available Materials");
2556                 uiDefButBitS(block, TOGN, ANIMFILTER_NOSKEY, REDRAWVIEW3D, "ShapeKey",235, -42, 75, 19, &vd->keyflags, 0, 0, 0, 0, "Show keyframes for any available Shape Keys");
2557         }
2558         uiBlockEndAlign(block);         
2559 }
2560
2561 static void view3d_panel_preview(ScrArea *sa, short cntrl)      // VIEW3D_HANDLER_PREVIEW
2562 {
2563         uiBlock *block;
2564         View3D *v3d= sa->spacedata.first;
2565         int ofsx, ofsy;
2566         
2567         block= uiNewBlock(&sa->uiblocks, "view3d_panel_preview", UI_EMBOSS, UI_HELV, sa->win);
2568         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | UI_PNL_SCALE | cntrl);
2569         uiSetPanelHandler(VIEW3D_HANDLER_PREVIEW);  // for close and esc
2570         
2571         ofsx= -150+(sa->winx/2)/v3d->blockscale;
2572         ofsy= -100+(sa->winy/2)/v3d->blockscale;
2573         if(uiNewPanel(sa, block, "Preview", "View3d", ofsx, ofsy, 300, 200)==0) return;
2574
2575         uiBlockSetDrawExtraFunc(block, BIF_view3d_previewdraw);
2576         
2577         if(G.scene->recalc & SCE_PRV_CHANGED) {
2578                 G.scene->recalc &= ~SCE_PRV_CHANGED;
2579                 //printf("found recalc\n");
2580                 BIF_view3d_previewrender_free(sa->spacedata.first);
2581                 BIF_preview_changed(0);
2582         }
2583 }
2584
2585 static void view3d_panel_gpencil(short cntrl)   // VIEW3D_HANDLER_GREASEPENCIL
2586 {
2587         uiBlock *block;
2588         View3D *vd;
2589         
2590         vd= G.vd;
2591
2592         block= uiNewBlock(&curarea->uiblocks, "view3d_panel_gpencil", UI_EMBOSS, UI_HELV, curarea->win);
2593         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE  | cntrl);
2594         uiSetPanelHandler(VIEW3D_HANDLER_GREASEPENCIL);  // for close and esc
2595         if (uiNewPanel(curarea, block, "Grease Pencil", "View3d", 100, 30, 318, 204)==0) return;
2596
2597         if (G.f & (G_VERTEXPAINT|G_WEIGHTPAINT|G_TEXTUREPAINT|G_GREASEPENCIL)) {
2598                 uiBlockSetFlag(block, UI_BLOCK_FRONTBUFFER);    // force old style frontbuffer draw
2599         }
2600         
2601         /* allocate memory for gpd if drawing enabled (this must be done first or else we crash) */
2602         if (vd->flag2 & V3D_DISPGP) {
2603                 if (vd->gpd == NULL)
2604                         gpencil_data_setactive(curarea, gpencil_data_addnew());
2605         }
2606         
2607         if (vd->flag2 & V3D_DISPGP) {
2608                 bGPdata *gpd= vd->gpd;
2609                 short newheight;
2610                 
2611                 /* this is a variable height panel, newpanel doesnt force new size on existing panels */
2612                 /* so first we make it default height */
2613                 uiNewPanelHeight(block, 204);
2614                 
2615                 /* draw button for showing gpencil settings and drawings */
2616                 uiDefButBitS(block, TOG, V3D_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &vd->flag2, 0, 0, 0, 0, "Display freehand annotations overlay over this 3D View (draw using Shift-LMB)");
2617                 
2618                 /* extend the panel if the contents won't fit */
2619                 newheight= draw_gpencil_panel(block, gpd, curarea); 
2620                 uiNewPanelHeight(block, newheight);
2621         }
2622         else {
2623                 uiDefButBitS(block, TOG, V3D_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &vd->flag2, 0, 0, 0, 0, "Display freehand annotations overlay over this 3D View");
2624                 uiDefBut(block, LABEL, 1, " ",  160, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
2625         }
2626 }
2627
2628
2629 static void view3d_blockhandlers(ScrArea *sa)
2630 {
2631         View3D *v3d= sa->spacedata.first;
2632         short a;
2633         
2634         /* warning; blocks need to be freed each time, handlers dont remove */
2635         uiFreeBlocksWin(&sa->uiblocks, sa->win);
2636         
2637         /*uv face-sel and wp mode when mixed with wire leave depth enabled causing
2638         models to draw over the UI */
2639         glDisable(GL_DEPTH_TEST); 
2640         
2641         for(a=0; a<SPACE_MAXHANDLER; a+=2) {
2642                 switch(v3d->blockhandler[a]) {
2643                 case VIEW3D_HANDLER_PROPERTIES:
2644                         view3d_panel_properties(v3d->blockhandler[a+1]);
2645                         break;
2646                 case VIEW3D_HANDLER_BACKGROUND:
2647                         view3d_panel_background(v3d->blockhandler[a+1]);
2648                         break;
2649                 case VIEW3D_HANDLER_OBJECT:
2650                         view3d_panel_object(v3d->blockhandler[a+1]);
2651                         break;
2652                 case VIEW3D_HANDLER_PREVIEW:
2653                         view3d_panel_preview(sa, v3d->blockhandler[a+1]);
2654                         break;                  
2655                 case VIEW3D_HANDLER_TRANSFORM:
2656                         view3d_panel_transform_spaces(v3d->blockhandler[a+1]);
2657                         break;
2658                 case VIEW3D_HANDLER_GREASEPENCIL:
2659                         view3d_panel_gpencil(v3d->blockhandler[a+1]);
2660                         break;
2661                 }
2662                 /* clear action value for event */
2663                 v3d->blockhandler[a+1]= 0;
2664         }
2665         uiDrawBlocksPanels(sa, 0);
2666
2667 }
2668
2669 /* ****************** View3d afterdraw *************** */
2670
2671 typedef struct View3DAfter {
2672         struct View3DAfter *next, *prev;
2673         struct Base *base;
2674         int type, flag;
2675 } View3DAfter;
2676
2677 /* temp storage of Objects that need to be drawn as last */
2678 void add_view3d_after(View3D *v3d, Base *base, int type, int flag)
2679 {
2680         View3DAfter *v3da= MEM_callocN(sizeof(View3DAfter), "View 3d after");
2681
2682         BLI_addtail(&v3d->afterdraw, v3da);
2683         v3da->base= base;
2684         v3da->type= type;
2685         v3da->flag= flag;
2686 }
2687
2688 /* clears zbuffer and draws it over */
2689 static void view3d_draw_xray(View3D *v3d, int clear)
2690 {
2691         View3DAfter *v3da, *next;
2692         int doit= 0;
2693         
2694         for(v3da= v3d->afterdraw.first; v3da; v3da= v3da->next)
2695                 if(v3da->type==V3D_XRAY) doit= 1;
2696         
2697         if(doit) {
2698                 if(clear && v3d->zbuf) glClear(GL_DEPTH_BUFFER_BIT);
2699                 v3d->xray= TRUE;
2700                 
2701                 for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
2702                         next= v3da->next;
2703                         if(v3da->type==V3D_XRAY) {
2704                                 draw_object(v3da->base, v3da->flag);
2705                                 BLI_remlink(&v3d->afterdraw, v3da);
2706                                 MEM_freeN(v3da);
2707                         }
2708                 }
2709                 v3d->xray= FALSE;
2710         }
2711 }
2712
2713 /* disables write in zbuffer and draws it over */
2714 static void view3d_draw_transp(View3D *v3d)
2715 {
2716         View3DAfter *v3da, *next;
2717
2718         glDepthMask(0);
2719         v3d->transp= TRUE;
2720
2721         for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
2722                 next= v3da->next;
2723                 if(v3da->type==V3D_TRANSP) {
2724                         draw_object(v3da->base, v3da->flag);
2725                         BLI_remlink(&v3d->afterdraw, v3da);
2726                         MEM_freeN(v3da);
2727                 }
2728         }
2729         v3d->transp= FALSE;
2730
2731         glDepthMask(1);
2732
2733 }
2734
2735 /* *********************** */
2736
2737 /*
2738         In most cases call draw_dupli_objects,
2739         draw_dupli_objects_color was added because when drawing set dupli's
2740         we need to force the color
2741 */
2742 static void draw_dupli_objects_color(View3D *v3d, Base *base, int color)
2743 {       
2744         ListBase *lb;
2745         DupliObject *dob;
2746         Base tbase;
2747         BoundBox *bb= NULL;
2748         GLuint displist=0;
2749         short transflag, use_displist= -1;      /* -1 is initialize */
2750         char dt, dtx;
2751         
2752         if (base->object->restrictflag & OB_RESTRICT_VIEW) return;
2753         
2754         tbase.flag= OB_FROMDUPLI|base->flag;
2755         lb= object_duplilist(G.scene, base->object);
2756
2757         for(dob= lb->first; dob; dob= dob->next) {
2758                 if(dob->no_draw);
2759                 else {
2760                         tbase.object= dob->ob;
2761                         
2762                         /* extra service: draw the duplicator in drawtype of parent */
2763                         /* MIN2 for the drawtype to allow bounding box objects in groups for lods */
2764                         dt= tbase.object->dt;   tbase.object->dt= MIN2(tbase.object->dt, base->object->dt);
2765                         dtx= tbase.object->dtx; tbase.object->dtx= base->object->dtx;
2766                         
2767                         /* negative scale flag has to propagate */
2768                         transflag= tbase.object->transflag;
2769                         if(base->object->transflag & OB_NEG_SCALE)
2770                                 tbase.object->transflag ^= OB_NEG_SCALE;
2771                         
2772                         BIF_ThemeColorBlend(color, TH_BACK, 0.5);
2773                         
2774                         /* generate displist, test for new object */
2775                         if(use_displist==1 && dob->prev && dob->prev->ob!=dob->ob) {
2776                                 use_displist= -1;
2777                                 glDeleteLists(displist, 1);
2778                         }
2779                         /* generate displist */
2780                         if(use_displist == -1) {
2781                                 
2782                                 /* lamp drawing messes with matrices, could be handled smarter... but this works */
2783                                 if(dob->ob->type==OB_LAMP || dob->type==OB_DUPLIGROUP)
2784                                         use_displist= 0;
2785                                 else {
2786                                         /* disable boundbox check for list creation */
2787                                         object_boundbox_flag(dob->ob, OB_BB_DISABLED, 1);
2788                                         /* need this for next part of code */
2789                                         bb= object_get_boundbox(dob->ob);
2790                                         
2791                                         Mat4One(dob->ob->obmat);        /* obmat gets restored */
2792                                         
2793                                         displist= glGenLists(1);
2794                                         glNewList(displist, GL_COMPILE);
2795                                         draw_object(&tbase, DRAW_CONSTCOLOR);
2796                                         glEndList();
2797                                         
2798                                         use_displist= 1;
2799                                         object_boundbox_flag(dob->ob, OB_BB_DISABLED, 0);
2800                                 }
2801                         }
2802                         if(use_displist) {
2803                                 mymultmatrix(dob->mat);
2804                                 if(boundbox_clip(dob->mat, bb))
2805                                    glCallList(displist);
2806                                 myloadmatrix(G.vd->viewmat);
2807                         }
2808                         else {
2809                                 Mat4CpyMat4(dob->ob->obmat, dob->mat);
2810                                 draw_object(&tbase, DRAW_CONSTCOLOR);
2811                         }
2812                         
2813                         tbase.object->dt= dt;
2814                         tbase.object->dtx= dtx;
2815                         tbase.object->transflag= transflag;
2816                 }
2817         }
2818         
2819         /* Transp afterdraw disabled, afterdraw only stores base pointers, and duplis can be same obj */
2820         
2821         free_object_duplilist(lb);      /* does restore */
2822         
2823         if(use_displist)
2824                 glDeleteLists(displist, 1);
2825 }
2826
2827 static void draw_dupli_objects(View3D *v3d, Base *base)
2828 {
2829         /* define the color here so draw_dupli_objects_color can be called
2830          * from the set loop */
2831         
2832         int color= (base->flag & SELECT)?TH_SELECT:TH_WIRE;
2833         /* debug */
2834         if(base->object->dup_group && base->object->dup_group->id.us<1)
2835                 color= TH_REDALERT;
2836         
2837         draw_dupli_objects_color(v3d, base, color);
2838 }
2839
2840 void view3d_update_depths(View3D *v3d)
2841 {
2842         /* Create storage for, and, if necessary, copy depth buffer */
2843         if(!v3d->depths) v3d->depths= MEM_callocN(sizeof(ViewDepths),"ViewDepths");
2844         if(v3d->depths) {
2845                 ViewDepths *d= v3d->depths;
2846                 if(d->w != v3d->area->winx ||
2847                    d->h != v3d->area->winy ||
2848                    !d->depths) {
2849                         d->w= v3d->area->winx;
2850                         d->h= v3d->area->winy;
2851                         if(d->depths)
2852                                 MEM_freeN(d->depths);
2853                         d->depths= MEM_mallocN(sizeof(float)*d->w*d->h,"View depths");
2854                         d->damaged= 1;
2855                 }
2856                 
2857                 if(d->damaged) {
2858                         glReadPixels(v3d->area->winrct.xmin,v3d->area->winrct.ymin,d->w,d->h,
2859                                      GL_DEPTH_COMPONENT,GL_FLOAT, d->depths);
2860                         
2861                         glGetDoublev(GL_DEPTH_RANGE,d->depth_range);
2862                         
2863                         d->damaged= 0;
2864                 }
2865         }
2866 }
2867
2868 /* Enable sculpting in wireframe mode by drawing sculpt object only to the depth buffer */
2869 static void draw_sculpt_depths(View3D *v3d)
2870 {
2871         Object *ob = OBACT;
2872
2873         int dt= MIN2(v3d->drawtype, ob->dt);
2874         if(v3d->zbuf==0 && dt>OB_WIRE)
2875                 dt= OB_WIRE;
2876         if(dt == OB_WIRE) {
2877                 GLboolean depth_on;
2878                 int orig_vdt = v3d->drawtype;
2879                 int orig_zbuf = v3d->zbuf;
2880                 int orig_odt = ob->dt;
2881
2882                 glGetBooleanv(GL_DEPTH_TEST, &depth_on);
2883                 v3d->drawtype = ob->dt = OB_SOLID;
2884                 v3d->zbuf = 1;
2885
2886                 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
2887                 glEnable(GL_DEPTH_TEST);
2888                 draw_object(BASACT, 0);
2889                 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2890                 if(!depth_on)
2891                         glDisable(GL_DEPTH_TEST);
2892
2893                 v3d->drawtype = orig_vdt;
2894                 v3d->zbuf = orig_zbuf;
2895                 ob->dt = orig_odt;
2896         }
2897 }
2898
2899 void draw_depth(ScrArea *sa, void *spacedata, int (* func)(void *))
2900 {
2901         View3D *v3d= spacedata;
2902         Base *base;
2903         Scene *sce;
2904         short zbuf, flag;
2905         float glalphaclip;
2906         /* temp set drawtype to solid */
2907         
2908         /* Setting these temporarily is not nice */
2909         zbuf = v3d->zbuf;
2910         flag = v3d->flag;
2911         glalphaclip = U.glalphaclip;
2912         
2913         U.glalphaclip = 0.5; /* not that nice but means we wont zoom into billboards */
2914         v3d->flag &= ~V3D_SELECT_OUTLINE;
2915
2916         setwinmatrixview3d(sa->winx, sa->winy, NULL);   /* 0= no pick rect */
2917         setviewmatrixview3d();  /* note: calls where_is_object for camera... */
2918         
2919         Mat4MulMat4(v3d->persmat, v3d->viewmat, sa->winmat);
2920         Mat4Invert(v3d->persinv, v3d->persmat);
2921         Mat4Invert(v3d->viewinv, v3d->viewmat);
2922         
2923         glClear(GL_DEPTH_BUFFER_BIT);
2924         
2925         myloadmatrix(v3d->viewmat);
2926         persp(PERSP_STORE);  // store correct view for persp(PERSP_VIEW) calls
2927         
2928         if(v3d->flag & V3D_CLIPPING) {
2929                 view3d_set_clipping(v3d);
2930         }
2931         
2932         v3d->zbuf= TRUE;
2933         glEnable(GL_DEPTH_TEST);
2934         
2935         /* draw set first */
2936         if(G.scene->set) {
2937                 for(SETLOOPER(G.scene->set, base)) {
2938                         if(v3d->lay & base->lay) {
2939                                 if (func == NULL || func(base)) {
2940                                         draw_object(base, 0);
2941                                         if(base->object->transflag & OB_DUPLI) {
2942                                                 draw_dupli_objects_color(v3d, base, TH_WIRE);
2943                                         }
2944                                 }
2945                         }
2946                 }
2947         }
2948         
2949         for(base= G.scene->base.first; base; base= base->next) {
2950                 if(v3d->lay & base->lay) {
2951                         if (func == NULL || func(base)) {
2952                                 /* dupli drawing */
2953                                 if(base->object->transflag & OB_DUPLI) {
2954                                         draw_dupli_objects(v3d, base);
2955                                 }
2956                                 draw_object(base, 0);
2957                         }
2958                 }
2959         }
2960         
2961         /* this isnt that nice, draw xray objects as if they are normal */
2962         if (v3d->afterdraw.first) {
2963                 View3DAfter *v3da, *next;
2964                 int num = 0;
2965                 v3d->xray= TRUE;
2966                 
2967                 glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */
2968                 for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
2969                         next= v3da->next;
2970                         if(v3da->type==V3D_XRAY) {
2971                                 draw_object(v3da->base, 0);
2972                                 num++;
2973                         }
2974                         /* dont remove this time */
2975                 }
2976                 v3d->xray= FALSE;
2977                 
2978                 glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */
2979                 for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
2980                         next= v3da->next;
2981                         if(v3da->type==V3D_XRAY) {
2982                                 v3d->xray= TRUE; v3d->transp= FALSE;  
2983                         } else if (v3da->type==V3D_TRANSP) {
2984                                 v3d->xray= FALSE; v3d->transp= TRUE;
2985                         }
2986                         
2987                         draw_object(v3da->base, 0); /* Draw Xray or Transp objects normally */
2988                         BLI_remlink(&v3d->afterdraw, v3da);
2989                         MEM_freeN(v3da);
2990                 }
2991                 v3d->xray= FALSE;
2992                 v3d->transp= FALSE;
2993         }
2994         
2995         v3d->zbuf = zbuf;
2996         U.glalphaclip = glalphaclip;
2997         v3d->flag = flag;
2998 }
2999
3000 static void draw_viewport_fps(ScrArea *sa);
3001
3002 typedef struct View3DShadow{
3003         struct View3DShadow*next, *prev;
3004         GPULamp *lamp;
3005 } View3DShadow;
3006
3007 static void gpu_render_lamp_update(View3D *v3d, Object *ob, Object *par, float obmat[][4], ListBase *shadows)
3008 {
3009         GPULamp *lamp;
3010         View3DShadow *shadow;
3011
3012         lamp = GPU_lamp_from_blender(G.scene, ob, par);
3013
3014         if(lamp) {
3015                 GPU_lamp_update(lamp, ob->lay, obmat);
3016                 
3017                 if((ob->lay & v3d->lay) && GPU_lamp_has_shadow_buffer(lamp)) {
3018                         shadow= MEM_callocN(sizeof(View3DShadow), "View3DShadow");
3019                         shadow->lamp = lamp;
3020                         BLI_addtail(shadows, shadow);
3021                 }
3022         }
3023 }
3024
3025 static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d)
3026 {
3027         ListBase shadows;
3028         View3DShadow *shadow;
3029         Scene *sce;
3030         Base *base;
3031         Object *ob;
3032
3033         shadows.first= shadows.last= NULL;
3034
3035         /* update lamp transform and gather shadow lamps */
3036         for(SETLOOPER(G.scene, base)) {
3037                 ob= base->object;
3038
3039                 if(ob->type == OB_LAMP)
3040                         gpu_render_lamp_update(v3d, ob, NULL, ob->obmat, &shadows);
3041
3042                 if (ob->transflag & OB_DUPLI) {
3043                         DupliObject *dob;
3044                         ListBase *lb = object_duplilist(G.scene, ob);
3045                         
3046                         for(dob=lb->first; dob; dob=dob->next)
3047                                 if(dob->ob->type==OB_LAMP)
3048                                         gpu_render_lamp_update(v3d, dob->ob, ob, dob->mat, &shadows);
3049                         
3050                         free_object_duplilist(lb);
3051                 }
3052         }
3053
3054         /* render shadows after updating all lamps, nested object_duplilist
3055          * don't work correct since it's replacing object matrices */
3056         for(shadow=shadows.first; shadow; shadow=shadow->next) {
3057                 /* this needs to be done better .. */
3058                 float viewmat[4][4], winmat[4][4];
3059                 int drawtype, lay, winsize, flag2;
3060
3061                 drawtype= v3d->drawtype;
3062                 lay= v3d->lay;
3063                 flag2= v3d->flag2 & V3D_SOLID_TEX;
3064
3065                 v3d->drawtype = OB_SOLID;
3066                 v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp);
3067                 v3d->flag2 &= ~V3D_SOLID_TEX;
3068
3069                 GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat);
3070                 drawview3d_render(v3d, viewmat, winsize, winsize, winmat, 1);
3071                 GPU_lamp_shadow_buffer_unbind(shadow->lamp);
3072
3073                 v3d->drawtype= drawtype;
3074                 v3d->lay= lay;
3075                 v3d->flag2 |= flag2;
3076         }
3077
3078         BLI_freelistN(&shadows);
3079 }
3080
3081 void drawview3dspace(ScrArea *sa, void *spacedata)
3082 {
3083         View3D *v3d= spacedata;
3084         Base *base;
3085         Object *ob;
3086         Scene *sce;
3087         char retopo, sculptparticle;
3088         Object *obact = OBACT;
3089         
3090         /* update all objects, ipos, matrices, displists, etc. Flags set by depgraph or manual, 
3091            no layer check here, gets correct flushed */
3092         /* sets first, we allow per definition current scene to have dependencies on sets */
3093         if(G.scene->set) {
3094                 for(SETLOOPER(G.scene->set, base))
3095                         object_handle_update(base->object);   // bke_object.h
3096         }
3097         
3098         v3d->lay_used = 0;
3099         for(base= G.scene->base.first; base; base= base->next) {
3100                 object_handle_update(base->object);   // bke_object.h
3101                 v3d->lay_used |= base->lay;
3102         }
3103
3104         /* shadow buffers, before we setup matrices */
3105         if(draw_glsl_material(NULL, v3d->drawtype))
3106                 gpu_update_lamps_shadows(G.scene, v3d);
3107         
3108         setwinmatrixview3d(sa->winx, sa->winy, NULL);   /* 0= no pick rect */
3109         setviewmatrixview3d();  /* note: calls where_is_object for camera... */
3110
3111         Mat4MulMat4(v3d->persmat, v3d->viewmat, sa->winmat);
3112         Mat4Invert(v3d->persinv, v3d->persmat);
3113         Mat4Invert(v3d->viewinv, v3d->viewmat);
3114
3115         /* calculate pixelsize factor once, is used for lamps and obcenters */
3116         {
3117                 float len1, len2, vec[3];
3118
3119                 VECCOPY(vec, v3d->persinv[0]);
3120                 len1= Normalize(vec);
3121                 VECCOPY(vec, v3d->persinv[1]);
3122                 len2= Normalize(vec);
3123                 
3124                 v3d->pixsize= 2.0f*(len1>len2?len1:len2);
3125                 
3126                 /* correct for window size */
3127                 if(sa->winx > sa->winy) v3d->pixsize/= (float)sa->winx;
3128                 else v3d->pixsize/= (float)sa->winy;
3129         }
3130         
3131         if(v3d->drawtype > OB_WIRE) {
3132                 float col[3];
3133                 BIF_GetThemeColor3fv(TH_BACK, col);
3134                 glClearColor(col[0], col[1], col[2], 0.0); 
3135                 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
3136                 
3137                 glLoadIdentity();
3138         }
3139         else {
3140                 float col[3];
3141                 BIF_GetThemeColor3fv(TH_BACK, col);
3142                 glClearColor(col[0], col[1], col[2], 0.0);
3143                 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
3144         }
3145         
3146         myloadmatrix(v3d->viewmat);
3147         persp(PERSP_STORE);  // store correct view for persp(PERSP_VIEW) calls
3148
3149         if(v3d->flag & V3D_CLIPPING)
3150                 view3d_draw_clipping(v3d);
3151         
3152         /* set zbuffer after we draw clipping region */