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