Fix for bug #7986: tab in edit introduces garbage values.
[plumiferos.git] / source / blender / src / drawview.c
blobe8657813f262314f339358bc33406885d8bbf6aa
1 /**
2 * $Id: drawview.c 12979 2007-12-23 17:01:44Z schlaile $
4 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version. The Blender
10 * Foundation also sells licenses for use in proprietary software under
11 * the Blender License. See http://www.blender.org/BL/ for information
12 * about this.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24 * All rights reserved.
26 * The Original Code is: all of this file.
28 * Contributor(s): none yet.
30 * ***** END GPL/BL DUAL LICENSE BLOCK *****
33 //#define NAN_LINEAR_PHYSICS
35 #include <math.h>
36 #include <string.h>
38 #ifndef WIN32
39 #include <unistd.h>
40 #include <sys/times.h>
41 #else
42 #include <io.h>
43 #endif
45 #ifdef WIN32
46 #ifndef snprintf
47 #define snprintf _snprintf
48 #endif
49 #endif
51 #include "MEM_guardedalloc.h"
53 #include "PIL_time.h"
55 #include "BMF_Api.h"
57 #include "IMB_imbuf_types.h"
58 #include "IMB_imbuf.h"
60 #include "DNA_action_types.h"
61 #include "DNA_armature_types.h"
62 #include "DNA_brush_types.h"
63 #include "DNA_camera_types.h"
64 #include "DNA_constraint_types.h"
65 #include "DNA_curve_types.h"
66 #include "DNA_group_types.h"
67 #include "DNA_image_types.h"
68 #include "DNA_key_types.h"
69 #include "DNA_lattice_types.h"
70 #include "DNA_mesh_types.h"
71 #include "DNA_meshdata_types.h"
72 #include "DNA_meta_types.h"
73 #include "DNA_object_types.h"
74 #include "DNA_screen_types.h"
75 #include "DNA_scene_types.h"
76 #include "DNA_space_types.h"
77 #include "DNA_texture_types.h"
78 #include "DNA_userdef_types.h"
79 #include "DNA_view3d_types.h"
80 #include "DNA_world_types.h"
82 #include "BLI_blenlib.h"
83 #include "BLI_arithb.h"
84 #include "BLI_editVert.h"
86 #include "BKE_action.h"
87 #include "BKE_armature.h"
88 #include "BKE_anim.h"
89 #include "BKE_constraint.h"
90 #include "BKE_curve.h"
91 #include "BKE_customdata.h"
92 #include "BKE_displist.h"
93 #include "BKE_depsgraph.h"
94 #include "BKE_DerivedMesh.h"
95 #include "BKE_global.h"
96 #include "BKE_lattice.h"
97 #include "BKE_library.h"
98 #include "BKE_image.h"
99 #include "BKE_ipo.h"
100 #include "BKE_key.h"
101 #include "BKE_main.h"
102 #include "BKE_mesh.h"
103 #include "BKE_object.h"
104 #include "BKE_scene.h"
105 #include "BKE_texture.h"
106 #include "BKE_utildefines.h"
108 #include "BIF_butspace.h"
109 #include "BIF_drawimage.h"
110 #include "BIF_editgroup.h"
111 #include "BIF_editarmature.h"
112 #include "BIF_editmesh.h"
113 #include "BIF_gl.h"
114 #include "BIF_glutil.h"
115 #include "BIF_interface.h"
116 #include "BIF_interface_icons.h"
117 #include "BIF_mywindow.h"
118 #include "BIF_poseobject.h"
119 #include "BIF_previewrender.h"
120 #include "BIF_resources.h"
121 #include "BIF_retopo.h"
122 #include "BIF_screen.h"
123 #include "BIF_space.h"
125 #ifdef WITH_VERSE
126 #include "BIF_verse.h"
127 #endif
129 #include "BDR_drawmesh.h"
130 #include "BDR_drawobject.h"
131 #include "BDR_editobject.h"
132 #include "BDR_vpaint.h"
133 #include "BDR_sculptmode.h"
135 #include "BSE_drawview.h"
136 #include "BSE_filesel.h"
137 #include "BSE_headerbuttons.h"
138 #include "BSE_seqaudio.h"
139 #include "BSE_trans_types.h"
140 #include "BSE_time.h"
141 #include "BSE_view.h"
143 #include "BPY_extern.h"
145 #include "RE_render_ext.h"
147 #include "blendef.h"
148 #include "mydevice.h"
149 #include "butspace.h" // event codes
151 #include "BIF_transform.h"
153 #include "RE_pipeline.h" // make_stars
155 #include "multires.h"
157 /* For MULTISAMPLE_ARB #define.
158 Note that older systems like irix
159 may not have this, and will need a #ifdef
160 to disable it.*/
161 /* #include "GL/glext.h" Disabled for release, to avoid possibly breaking platforms.
162 Instead, the define we need will just be #defined if it's not in the platform opengl.h.
165 /* Modules used */
166 #include "radio.h"
168 /* locals */
169 void drawname(Object *ob);
171 static void star_stuff_init_func(void)
173 cpack(-1);
174 glPointSize(1.0);
175 glBegin(GL_POINTS);
177 static void star_stuff_vertex_func(float* i)
179 glVertex3fv(i);
181 static void star_stuff_term_func(void)
183 glEnd();
186 void default_gl_light(void)
188 int a;
190 /* initialize */
191 if(U.light[0].flag==0 && U.light[1].flag==0 && U.light[2].flag==0) {
192 U.light[0].flag= 1;
193 U.light[0].vec[0]= -0.3; U.light[0].vec[1]= 0.3; U.light[0].vec[2]= 0.9;
194 U.light[0].col[0]= 0.8; U.light[0].col[1]= 0.8; U.light[0].col[2]= 0.8;
195 U.light[0].spec[0]= 0.5; U.light[0].spec[1]= 0.5; U.light[0].spec[2]= 0.5;
196 U.light[0].spec[3]= 1.0;
198 U.light[1].flag= 0;
199 U.light[1].vec[0]= 0.5; U.light[1].vec[1]= 0.5; U.light[1].vec[2]= 0.1;
200 U.light[1].col[0]= 0.4; U.light[1].col[1]= 0.4; U.light[1].col[2]= 0.8;
201 U.light[1].spec[0]= 0.3; U.light[1].spec[1]= 0.3; U.light[1].spec[2]= 0.5;
202 U.light[1].spec[3]= 1.0;
204 U.light[2].flag= 0;
205 U.light[2].vec[0]= 0.3; U.light[2].vec[1]= -0.3; U.light[2].vec[2]= -0.2;
206 U.light[2].col[0]= 0.8; U.light[2].col[1]= 0.5; U.light[2].col[2]= 0.4;
207 U.light[2].spec[0]= 0.5; U.light[2].spec[1]= 0.4; U.light[2].spec[2]= 0.3;
208 U.light[2].spec[3]= 1.0;
212 glLightfv(GL_LIGHT0, GL_POSITION, U.light[0].vec);
213 glLightfv(GL_LIGHT0, GL_DIFFUSE, U.light[0].col);
214 glLightfv(GL_LIGHT0, GL_SPECULAR, U.light[0].spec);
216 glLightfv(GL_LIGHT1, GL_POSITION, U.light[1].vec);
217 glLightfv(GL_LIGHT1, GL_DIFFUSE, U.light[1].col);
218 glLightfv(GL_LIGHT1, GL_SPECULAR, U.light[1].spec);
220 glLightfv(GL_LIGHT2, GL_POSITION, U.light[2].vec);
221 glLightfv(GL_LIGHT2, GL_DIFFUSE, U.light[2].col);
222 glLightfv(GL_LIGHT2, GL_SPECULAR, U.light[2].spec);
224 for(a=0; a<8; a++) {
225 if(a<3) {
226 if(U.light[a].flag) glEnable(GL_LIGHT0+a);
227 else glDisable(GL_LIGHT0+a);
229 // clear stuff from other opengl lamp usage
230 glLightf(GL_LIGHT0+a, GL_SPOT_CUTOFF, 180.0);
231 glLightf(GL_LIGHT0+a, GL_CONSTANT_ATTENUATION, 1.0);
232 glLightf(GL_LIGHT0+a, GL_LINEAR_ATTENUATION, 0.0);
234 else glDisable(GL_LIGHT0+a);
237 glDisable(GL_LIGHTING);
239 glDisable(GL_COLOR_MATERIAL);
242 /* also called when render 'ogl' */
243 void init_gl_stuff(void)
245 float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 };
246 float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
247 float mat_shininess[] = { 35.0 };
248 int a, x, y;
249 GLubyte pat[32*32];
250 const GLubyte *patc= pat;
253 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
254 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular);
255 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
256 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
258 default_gl_light();
260 /* no local viewer, looks ugly in ortho mode */
261 /* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */
263 glDepthFunc(GL_LEQUAL);
264 /* scaling matrices */
265 glEnable(GL_NORMALIZE);
267 glShadeModel(GL_FLAT);
269 glDisable(GL_ALPHA_TEST);
270 glDisable(GL_BLEND);
271 glDisable(GL_DEPTH_TEST);
272 glDisable(GL_FOG);
273 glDisable(GL_LIGHTING);
274 glDisable(GL_LOGIC_OP);
275 glDisable(GL_STENCIL_TEST);
276 glDisable(GL_TEXTURE_1D);
277 glDisable(GL_TEXTURE_2D);
279 /* default on, disable/enable should be local per function */
280 glEnableClientState(GL_VERTEX_ARRAY);
281 glEnableClientState(GL_NORMAL_ARRAY);
283 glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
284 glPixelTransferi(GL_RED_SCALE, 1);
285 glPixelTransferi(GL_RED_BIAS, 0);
286 glPixelTransferi(GL_GREEN_SCALE, 1);
287 glPixelTransferi(GL_GREEN_BIAS, 0);
288 glPixelTransferi(GL_BLUE_SCALE, 1);
289 glPixelTransferi(GL_BLUE_BIAS, 0);
290 glPixelTransferi(GL_ALPHA_SCALE, 1);
291 glPixelTransferi(GL_ALPHA_BIAS, 0);
293 glPixelTransferi(GL_DEPTH_BIAS, 0);
294 glPixelTransferi(GL_DEPTH_SCALE, 1);
295 glDepthRange(0.0, 1.0);
297 a= 0;
298 for(x=0; x<32; x++) {
299 for(y=0; y<4; y++) {
300 if( (x) & 1) pat[a++]= 0x88;
301 else pat[a++]= 0x22;
305 glPolygonStipple(patc);
308 init_realtime_GL();
311 void circf(float x, float y, float rad)
313 GLUquadricObj *qobj = gluNewQuadric();
315 gluQuadricDrawStyle(qobj, GLU_FILL);
317 glPushMatrix();
319 glTranslatef(x, y, 0.);
321 gluDisk( qobj, 0.0, rad, 32, 1);
323 glPopMatrix();
325 gluDeleteQuadric(qobj);
328 void circ(float x, float y, float rad)
330 GLUquadricObj *qobj = gluNewQuadric();
332 gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
334 glPushMatrix();
336 glTranslatef(x, y, 0.);
338 gluDisk( qobj, 0.0, rad, 32, 1);
340 glPopMatrix();
342 gluDeleteQuadric(qobj);
345 /* ********** ********** */
347 static void draw_bgpic(void)
349 BGpic *bgpic;
350 Image *ima;
351 ImBuf *ibuf= NULL;
352 float vec[4], fac, asp, zoomx, zoomy;
353 float x1, y1, x2, y2, cx, cy;
355 bgpic= G.vd->bgpic;
356 if(bgpic==NULL) return;
358 ima= bgpic->ima;
360 if(ima)
361 ibuf= BKE_image_get_ibuf(ima, &bgpic->iuser);
362 if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL) )
363 return;
364 if(ibuf->channels!=4)
365 return;
366 if(ibuf->rect==NULL)
367 IMB_rect_from_float(ibuf);
369 if(G.vd->persp==2) {
370 rctf vb;
372 calc_viewborder(G.vd, &vb);
374 x1= vb.xmin;
375 y1= vb.ymin;
376 x2= vb.xmax;
377 y2= vb.ymax;
379 else {
380 float sco[2];
382 /* calc window coord */
383 initgrabz(0.0, 0.0, 0.0);
384 window_to_3d(vec, 1, 0);
385 fac= MAX3( fabs(vec[0]), fabs(vec[1]), fabs(vec[1]) );
386 fac= 1.0/fac;
388 asp= ( (float)ibuf->y)/(float)ibuf->x;
390 vec[0] = vec[1] = vec[2] = 0.0;
391 view3d_project_float(curarea, vec, sco, G.vd->persmat);
392 cx = sco[0];
393 cy = sco[1];
395 x1= cx+ fac*(bgpic->xof-bgpic->size);
396 y1= cy+ asp*fac*(bgpic->yof-bgpic->size);
397 x2= cx+ fac*(bgpic->xof+bgpic->size);
398 y2= cy+ asp*fac*(bgpic->yof+bgpic->size);
401 /* complete clip? */
403 if(x2 < 0 ) return;
404 if(y2 < 0 ) return;
405 if(x1 > curarea->winx ) return;
406 if(y1 > curarea->winy ) return;
408 zoomx= (x2-x1)/ibuf->x;
409 zoomy= (y2-y1)/ibuf->y;
411 /* for some reason; zoomlevels down refuses to use GL_ALPHA_SCALE */
412 if(zoomx < 1.0f || zoomy < 1.0f) {
413 float tzoom= MIN2(zoomx, zoomy);
414 int mip= 0;
416 if(ibuf->mipmap[0]==NULL)
417 IMB_makemipmap(ibuf, 0);
419 while(tzoom < 1.0f && mip<8 && ibuf->mipmap[mip]) {
420 tzoom*= 2.0f;
421 zoomx*= 2.0f;
422 zoomy*= 2.0f;
423 mip++;
425 if(mip>0)
426 ibuf= ibuf->mipmap[mip-1];
429 if(G.vd->zbuf) glDisable(GL_DEPTH_TEST);
431 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
433 glMatrixMode(GL_PROJECTION);
434 glPushMatrix();
435 glMatrixMode(GL_MODELVIEW);
436 glPushMatrix();
438 glaDefine2DArea(&curarea->winrct);
440 glEnable(GL_BLEND);
442 glPixelZoom(zoomx, zoomy);
443 glColor4f(1.0, 1.0, 1.0, 1.0-bgpic->blend);
444 glaDrawPixelsTex(x1, y1, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect);
446 glPixelZoom(1.0, 1.0);
447 glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
449 glMatrixMode(GL_PROJECTION);
450 glPopMatrix();
451 glMatrixMode(GL_MODELVIEW);
452 glPopMatrix();
454 glDisable(GL_BLEND);
455 if(G.vd->zbuf) glEnable(GL_DEPTH_TEST);
457 areawinset(curarea->win); // restore viewport / scissor
460 static void drawgrid_draw(float wx, float wy, float x, float y, float dx)
462 float fx, fy;
464 x+= (wx);
465 y+= (wy);
466 fx= x/dx;
467 fx= x-dx*floor(fx);
469 while(fx< curarea->winx) {
470 fdrawline(fx, 0.0, fx, (float)curarea->winy);
471 fx+= dx;
474 fy= y/dx;
475 fy= y-dx*floor(fy);
478 while(fy< curarea->winy) {
479 fdrawline(0.0, fy, (float)curarea->winx, fy);
480 fy+= dx;
485 // not intern, called in editobject for constraint axis too
486 void make_axis_color(char *col, char *col2, char axis)
488 if(axis=='x') {
489 col2[0]= col[0]>219?255:col[0]+36;
490 col2[1]= col[1]<26?0:col[1]-26;
491 col2[2]= col[2]<26?0:col[2]-26;
493 else if(axis=='y') {
494 col2[0]= col[0]<46?0:col[0]-36;
495 col2[1]= col[1]>189?255:col[1]+66;
496 col2[2]= col[2]<46?0:col[2]-36;
498 else {
499 col2[0]= col[0]<26?0:col[0]-26;
500 col2[1]= col[1]<26?0:col[1]-26;
501 col2[2]= col[2]>209?255:col[2]+46;
506 static void drawgrid(void)
508 /* extern short bgpicmode; */
509 float wx, wy, x, y, fw, fx, fy, dx;
510 float vec4[4];
511 char col[3], col2[3];
512 short sublines = G.vd->gridsubdiv;
514 vec4[0]=vec4[1]=vec4[2]=0.0;
515 vec4[3]= 1.0;
516 Mat4MulVec4fl(G.vd->persmat, vec4);
517 fx= vec4[0];
518 fy= vec4[1];
519 fw= vec4[3];
521 wx= (curarea->winx/2.0); /* because of rounding errors, grid at wrong location */
522 wy= (curarea->winy/2.0);
524 x= (wx)*fx/fw;
525 y= (wy)*fy/fw;
527 vec4[0]=vec4[1]=G.vd->grid;
528 vec4[2]= 0.0;
529 vec4[3]= 1.0;
530 Mat4MulVec4fl(G.vd->persmat, vec4);
531 fx= vec4[0];
532 fy= vec4[1];
533 fw= vec4[3];
535 dx= fabs(x-(wx)*fx/fw);
536 if(dx==0) dx= fabs(y-(wy)*fy/fw);
538 glDepthMask(0); // disable write in zbuffer
540 /* check zoom out */
541 BIF_ThemeColor(TH_GRID);
542 persp(PERSP_WIN);
544 if(dx<6.0) {
545 G.vd->gridview*= sublines;
546 dx*= sublines;
548 if(dx<6.0) {
549 G.vd->gridview*= sublines;
550 dx*= sublines;
552 if(dx<6.0) {
553 G.vd->gridview*= sublines;
554 dx*=sublines;
555 if(dx<6.0);
556 else {
557 BIF_ThemeColor(TH_GRID);
558 drawgrid_draw(wx, wy, x, y, dx);
561 else { // start blending out
562 BIF_ThemeColorBlend(TH_BACK, TH_GRID, dx/60.0);
563 drawgrid_draw(wx, wy, x, y, dx);
565 BIF_ThemeColor(TH_GRID);
566 drawgrid_draw(wx, wy, x, y, sublines*dx);
569 else { // start blending out (6 < dx < 60)
570 BIF_ThemeColorBlend(TH_BACK, TH_GRID, dx/60.0);
571 drawgrid_draw(wx, wy, x, y, dx);
573 BIF_ThemeColor(TH_GRID);
574 drawgrid_draw(wx, wy, x, y, sublines*dx);
577 else {
578 if(dx>60.0) { // start blending in
579 G.vd->gridview/= sublines;
580 dx/= sublines;
581 if(dx>60.0) { // start blending in
582 G.vd->gridview/= sublines;
583 dx/= sublines;
584 if(dx>60.0) {
585 BIF_ThemeColor(TH_GRID);
586 drawgrid_draw(wx, wy, x, y, dx);
588 else {
589 BIF_ThemeColorBlend(TH_BACK, TH_GRID, dx/60.0);
590 drawgrid_draw(wx, wy, x, y, dx);
591 BIF_ThemeColor(TH_GRID);
592 drawgrid_draw(wx, wy, x, y, dx*sublines);
595 else {
596 BIF_ThemeColorBlend(TH_BACK, TH_GRID, dx/60.0);
597 drawgrid_draw(wx, wy, x, y, dx);
598 BIF_ThemeColor(TH_GRID);
599 drawgrid_draw(wx, wy, x, y, dx*sublines);
602 else {
603 BIF_ThemeColorBlend(TH_BACK, TH_GRID, dx/60.0);
604 drawgrid_draw(wx, wy, x, y, dx);
605 BIF_ThemeColor(TH_GRID);
606 drawgrid_draw(wx, wy, x, y, dx*sublines);
610 x+= (wx);
611 y+= (wy);
612 BIF_GetThemeColor3ubv(TH_GRID, col);
614 setlinestyle(0);
616 /* center cross */
617 if(G.vd->view==3) make_axis_color(col, col2, 'y');
618 else make_axis_color(col, col2, 'x');
619 glColor3ubv((GLubyte *)col2);
621 fdrawline(0.0, y, (float)curarea->winx, y);
623 if(G.vd->view==7) make_axis_color(col, col2, 'y');
624 else make_axis_color(col, col2, 'z');
625 glColor3ubv((GLubyte *)col2);
627 fdrawline(x, 0.0, x, (float)curarea->winy);
629 glDepthMask(1); // enable write in zbuffer
630 persp(PERSP_VIEW);
635 static void drawfloor(void)
637 View3D *vd;
638 float vert[3], grid;
639 int a, gridlines, emphasise;
640 char col[3], col2[3];
641 short draw_line = 0;
643 vd= curarea->spacedata.first;
645 vert[2]= 0.0;
647 if(vd->gridlines<3) return;
649 if(G.vd->zbuf && G.obedit) glDepthMask(0); // for zbuffer-select
651 gridlines= vd->gridlines/2;
652 grid= gridlines*vd->grid;
654 BIF_GetThemeColor3ubv(TH_GRID, col);
655 BIF_GetThemeColor3ubv(TH_BACK, col2);
657 /* emphasise division lines lighter instead of darker, if background is darker than grid */
658 if ( ((col[0]+col[1]+col[2])/3+10) > (col2[0]+col2[1]+col2[2])/3 )
659 emphasise = 20;
660 else
661 emphasise = -10;
663 /* draw the Y axis and/or grid lines */
664 for(a= -gridlines;a<=gridlines;a++) {
665 if(a==0) {
666 /* check for the 'show Y axis' preference */
667 if (vd->gridflag & V3D_SHOW_Y) {
668 make_axis_color(col, col2, 'y');
669 glColor3ubv((GLubyte *)col2);
671 draw_line = 1;
672 } else if (vd->gridflag & V3D_SHOW_FLOOR) {
673 BIF_ThemeColorShade(TH_GRID, emphasise);
674 } else {
675 draw_line = 0;
677 } else {
678 /* check for the 'show grid floor' preference */
679 if (vd->gridflag & V3D_SHOW_FLOOR) {
680 if( (a % 10)==0) {
681 BIF_ThemeColorShade(TH_GRID, emphasise);
683 else BIF_ThemeColorShade(TH_GRID, 10);
685 draw_line = 1;
686 } else {
687 draw_line = 0;
691 if (draw_line) {
692 glBegin(GL_LINE_STRIP);
693 vert[0]= a*vd->grid;
694 vert[1]= grid;
695 glVertex3fv(vert);
696 vert[1]= -grid;
697 glVertex3fv(vert);
698 glEnd();
702 /* draw the X axis and/or grid lines */
703 for(a= -gridlines;a<=gridlines;a++) {
704 if(a==0) {
705 /* check for the 'show X axis' preference */
706 if (vd->gridflag & V3D_SHOW_X) {
707 make_axis_color(col, col2, 'x');
708 glColor3ubv((GLubyte *)col2);
710 draw_line = 1;
711 } else if (vd->gridflag & V3D_SHOW_FLOOR) {
712 BIF_ThemeColorShade(TH_GRID, emphasise);
713 } else {
714 draw_line = 0;
716 } else {
717 /* check for the 'show grid floor' preference */
718 if (vd->gridflag & V3D_SHOW_FLOOR) {
719 if( (a % 10)==0) {
720 BIF_ThemeColorShade(TH_GRID, emphasise);
722 else BIF_ThemeColorShade(TH_GRID, 10);
724 draw_line = 1;
725 } else {
726 draw_line = 0;
730 if (draw_line) {
731 glBegin(GL_LINE_STRIP);
732 vert[1]= a*vd->grid;
733 vert[0]= grid;
734 glVertex3fv(vert );
735 vert[0]= -grid;
736 glVertex3fv(vert);
737 glEnd();
741 /* draw the Z axis line */
742 /* check for the 'show Z axis' preference */
743 if (vd->gridflag & V3D_SHOW_Z) {
744 make_axis_color(col, col2, 'z');
745 glColor3ubv((GLubyte *)col2);
747 glBegin(GL_LINE_STRIP);
748 vert[0]= 0;
749 vert[1]= 0;
750 vert[2]= grid;
751 glVertex3fv(vert );
752 vert[2]= -grid;
753 glVertex3fv(vert);
754 glEnd();
757 if(G.vd->zbuf && G.obedit) glDepthMask(1);
761 static void drawcursor(View3D *v3d)
763 short mx,my,co[2];
764 int flag;
766 /* we dont want the clipping for cursor */
767 flag= v3d->flag;
768 v3d->flag= 0;
769 project_short( give_cursor(), co);
770 v3d->flag= flag;
772 mx = co[0];
773 my = co[1];
775 if(mx!=IS_CLIPPED) {
776 setlinestyle(0);
777 cpack(0xFF);
778 circ((float)mx, (float)my, 10.0);
779 setlinestyle(4);
780 cpack(0xFFFFFF);
781 circ((float)mx, (float)my, 10.0);
782 setlinestyle(0);
783 cpack(0x0);
785 sdrawline(mx-20, my, mx-5, my);
786 sdrawline(mx+5, my, mx+20, my);
787 sdrawline(mx, my-20, mx, my-5);
788 sdrawline(mx, my+5, mx, my+20);
792 /* ********* custom clipping *********** */
794 static void view3d_draw_clipping(View3D *v3d)
796 BoundBox *bb= v3d->clipbb;
798 BIF_ThemeColorShade(TH_BACK, -8);
800 glBegin(GL_QUADS);
802 glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[1]); glVertex3fv(bb->vec[2]); glVertex3fv(bb->vec[3]);
803 glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[5]); glVertex3fv(bb->vec[1]);
804 glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[6]); glVertex3fv(bb->vec[5]);
805 glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[3]); glVertex3fv(bb->vec[2]); glVertex3fv(bb->vec[6]);
806 glVertex3fv(bb->vec[1]); glVertex3fv(bb->vec[5]); glVertex3fv(bb->vec[6]); glVertex3fv(bb->vec[2]);
807 glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[3]);
809 glEnd();
812 void view3d_set_clipping(View3D *v3d)
814 double plane[4];
815 int a;
817 for(a=0; a<4; a++) {
818 QUATCOPY(plane, v3d->clip[a]);
819 glClipPlane(GL_CLIP_PLANE0+a, plane);
820 glEnable(GL_CLIP_PLANE0+a);
824 void view3d_clr_clipping(void)
826 int a;
828 for(a=0; a<4; a++) {
829 glDisable(GL_CLIP_PLANE0+a);
833 int view3d_test_clipping(View3D *v3d, float *vec)
835 /* vec in world coordinates, returns 1 if clipped */
836 float view[3];
838 VECCOPY(view, vec);
840 if(0.0f < v3d->clip[0][3] + INPR(view, v3d->clip[0]))
841 if(0.0f < v3d->clip[1][3] + INPR(view, v3d->clip[1]))
842 if(0.0f < v3d->clip[2][3] + INPR(view, v3d->clip[2]))
843 if(0.0f < v3d->clip[3][3] + INPR(view, v3d->clip[3]))
844 return 0;
846 return 1;
849 /* ********* end custom clipping *********** */
851 static void view3d_get_viewborder_size(View3D *v3d, float size_r[2])
853 float winmax= MAX2(v3d->area->winx, v3d->area->winy);
854 float aspect= (float) (G.scene->r.xsch*G.scene->r.xasp)/(G.scene->r.ysch*G.scene->r.yasp);
856 if(aspect>1.0) {
857 size_r[0]= winmax;
858 size_r[1]= winmax/aspect;
859 } else {
860 size_r[0]= winmax*aspect;
861 size_r[1]= winmax;
865 void calc_viewborder(struct View3D *v3d, rctf *viewborder_r)
867 float zoomfac, size[2];
868 float dx= 0.0f, dy= 0.0f;
870 view3d_get_viewborder_size(v3d, size);
872 /* magic zoom calculation, no idea what
873 * it signifies, if you find out, tell me! -zr
875 /* simple, its magic dude!
876 * well, to be honest, this gives a natural feeling zooming
877 * with multiple keypad presses (ton)
880 zoomfac= (M_SQRT2 + v3d->camzoom/50.0);
881 zoomfac= (zoomfac*zoomfac)*0.25;
883 size[0]= size[0]*zoomfac;
884 size[1]= size[1]*zoomfac;
886 /* center in window */
887 viewborder_r->xmin= 0.5*v3d->area->winx - 0.5*size[0];
888 viewborder_r->ymin= 0.5*v3d->area->winy - 0.5*size[1];
889 viewborder_r->xmax= viewborder_r->xmin + size[0];
890 viewborder_r->ymax= viewborder_r->ymin + size[1];
892 dx= v3d->area->winx*G.vd->camdx*zoomfac*2.0f;
893 dy= v3d->area->winy*G.vd->camdy*zoomfac*2.0f;
895 /* apply offset */
896 viewborder_r->xmin-= dx;
897 viewborder_r->ymin-= dy;
898 viewborder_r->xmax-= dx;
899 viewborder_r->ymax-= dy;
901 if(v3d->camera && v3d->camera->type==OB_CAMERA) {
902 Camera *cam= v3d->camera->data;
903 float w = viewborder_r->xmax - viewborder_r->xmin;
904 float h = viewborder_r->ymax - viewborder_r->ymin;
905 float side = MAX2(w, h);
907 viewborder_r->xmin+= cam->shiftx*side;
908 viewborder_r->xmax+= cam->shiftx*side;
909 viewborder_r->ymin+= cam->shifty*side;
910 viewborder_r->ymax+= cam->shifty*side;
914 void view3d_set_1_to_1_viewborder(View3D *v3d)
916 float size[2];
917 int im_width= (G.scene->r.size*G.scene->r.xsch)/100;
919 view3d_get_viewborder_size(v3d, size);
921 v3d->camzoom= (sqrt(4.0*im_width/size[0]) - M_SQRT2)*50.0;
922 v3d->camzoom= CLAMPIS(v3d->camzoom, -30, 300);
926 static void drawviewborder_flymode(void)
928 /* draws 4 edge brackets that frame the safe area where the
929 mouse can move during fly mode without spinning the view */
930 float x1, x2, y1, y2;
932 x1= 0.45*(float)curarea->winx;
933 y1= 0.45*(float)curarea->winy;
934 x2= 0.55*(float)curarea->winx;
935 y2= 0.55*(float)curarea->winy;
936 cpack(0);
939 glBegin(GL_LINES);
940 /* bottom left */
941 glVertex2f(x1,y1);
942 glVertex2f(x1,y1+5);
944 glVertex2f(x1,y1);
945 glVertex2f(x1+5,y1);
947 /* top right */
948 glVertex2f(x2,y2);
949 glVertex2f(x2,y2-5);
951 glVertex2f(x2,y2);
952 glVertex2f(x2-5,y2);
954 /* top left */
955 glVertex2f(x1,y2);
956 glVertex2f(x1,y2-5);
958 glVertex2f(x1,y2);
959 glVertex2f(x1+5,y2);
961 /* bottom right */
962 glVertex2f(x2,y1);
963 glVertex2f(x2,y1+5);
965 glVertex2f(x2,y1);
966 glVertex2f(x2-5,y1);
967 glEnd();
971 static void drawviewborder(void)
973 extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad); // interface_panel.c
974 float fac, a;
975 float x1, x2, y1, y2;
976 float x3, y3, x4, y4;
977 rctf viewborder;
978 Camera *ca= NULL;
980 if(G.vd->camera==NULL)
981 return;
982 if(G.vd->camera->type==OB_CAMERA)
983 ca = G.vd->camera->data;
985 calc_viewborder(G.vd, &viewborder);
986 x1= viewborder.xmin;
987 y1= viewborder.ymin;
988 x2= viewborder.xmax;
989 y2= viewborder.ymax;
991 /* passepartout, specified in camera edit buttons */
992 if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001) {
993 if (ca->passepartalpha == 1.0) {
994 glColor3f(0, 0, 0);
995 } else {
996 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
997 glEnable(GL_BLEND);
998 glColor4f(0, 0, 0, ca->passepartalpha);
1000 if (x1 > 0.0)
1001 glRectf(0.0, (float)curarea->winy, x1, 0.0);
1002 if (x2 < (float)curarea->winx)
1003 glRectf(x2, (float)curarea->winy, (float)curarea->winx, 0.0);
1004 if (y2 < (float)curarea->winy)
1005 glRectf(x1, (float)curarea->winy, x2, y2);
1006 if (y2 > 0.0)
1007 glRectf(x1, y1, x2, 0.0);
1009 glDisable(GL_BLEND);
1012 /* edge */
1013 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1015 setlinestyle(0);
1016 BIF_ThemeColor(TH_BACK);
1017 glRectf(x1, y1, x2, y2);
1019 setlinestyle(3);
1020 BIF_ThemeColor(TH_WIRE);
1021 glRectf(x1, y1, x2, y2);
1023 /* camera name - draw in highlighted text colour */
1024 if (ca && (ca->flag & CAM_SHOWNAME)) {
1025 BIF_ThemeColor(TH_TEXT_HI);
1026 glRasterPos2f(x1, y1-15);
1028 BMF_DrawString(G.font, G.vd->camera->id.name+2);
1029 BIF_ThemeColor(TH_WIRE);
1033 /* border */
1034 if(G.scene->r.mode & R_BORDER) {
1036 cpack(0);
1037 x3= x1+ G.scene->r.border.xmin*(x2-x1);
1038 y3= y1+ G.scene->r.border.ymin*(y2-y1);
1039 x4= x1+ G.scene->r.border.xmax*(x2-x1);
1040 y4= y1+ G.scene->r.border.ymax*(y2-y1);
1042 cpack(0x4040FF);
1043 glRectf(x3, y3, x4, y4);
1046 /* safety border */
1047 if (ca && (ca->flag & CAM_SHOWTITLESAFE)) {
1048 fac= 0.1;
1050 a= fac*(x2-x1);
1051 x1+= a;
1052 x2-= a;
1054 a= fac*(y2-y1);
1055 y1+= a;
1056 y2-= a;
1058 BIF_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0);
1060 uiSetRoundBox(15);
1061 gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, 12.0);
1064 setlinestyle(0);
1065 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1069 void backdrawview3d(int test)
1071 struct Base *base;
1073 /*for 2.43 release, don't use glext and just define the constant.
1074 this to avoid possibly breaking platforms before release.*/
1075 #ifndef GL_MULTISAMPLE_ARB
1076 #define GL_MULTISAMPLE_ARB 0x809D
1077 #endif
1079 #ifdef GL_MULTISAMPLE_ARB
1080 int m;
1081 #endif
1083 if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT));
1084 else if(G.obedit && G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT));
1085 else {
1086 G.vd->flag &= ~V3D_NEEDBACKBUFDRAW;
1087 return;
1090 if( !(G.vd->flag & V3D_NEEDBACKBUFDRAW) ) return;
1092 if(test) {
1093 if(qtest()) {
1094 addafterqueue(curarea->win, BACKBUFDRAW, 1);
1095 return;
1098 persp(PERSP_VIEW);
1100 /*Disable FSAA for backbuffer selection.
1102 Only works if GL_MULTISAMPLE_ARB is defined by the header
1103 file, which is should be for every OS that supports FSAA.*/
1105 #ifdef GL_MULTISAMPLE_ARB
1106 m = glIsEnabled(GL_MULTISAMPLE_ARB);
1107 if (m) glDisable(GL_MULTISAMPLE_ARB);
1108 #endif
1110 #ifdef __APPLE__
1111 glDrawBuffer(GL_AUX0);
1112 #endif
1113 if(G.vd->drawtype > OB_WIRE) G.vd->zbuf= TRUE;
1114 curarea->win_swap &= ~WIN_BACK_OK;
1116 glDisable(GL_DITHER);
1118 glClearColor(0.0, 0.0, 0.0, 0.0);
1119 if(G.vd->zbuf) {
1120 glEnable(GL_DEPTH_TEST);
1121 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1123 else {
1124 glClear(GL_COLOR_BUFFER_BIT);
1125 glDisable(GL_DEPTH_TEST);
1128 if(G.vd->flag & V3D_CLIPPING)
1129 view3d_set_clipping(G.vd);
1131 G.f |= G_BACKBUFSEL;
1133 base= (G.scene->basact);
1134 if(base && (base->lay & G.vd->lay)) {
1135 draw_object_backbufsel(base->object);
1138 G.vd->flag &= ~V3D_NEEDBACKBUFDRAW;
1140 G.f &= ~G_BACKBUFSEL;
1141 G.vd->zbuf= FALSE;
1142 glDisable(GL_DEPTH_TEST);
1143 glEnable(GL_DITHER);
1145 #ifdef __APPLE__
1146 glDrawBuffer(GL_BACK); /* we were in aux buffers */
1147 #endif
1149 if(G.vd->flag & V3D_CLIPPING)
1150 view3d_clr_clipping();
1152 #ifdef GL_MULTISAMPLE_ARB
1153 if (m) glEnable(GL_MULTISAMPLE_ARB);
1154 #endif
1156 /* it is important to end a view in a transform compatible with buttons */
1157 persp(PERSP_WIN); // set ortho
1158 bwin_scalematrix(curarea->win, G.vd->blockscale, G.vd->blockscale, G.vd->blockscale);
1162 void check_backbuf(void)
1164 if(G.vd->flag & V3D_NEEDBACKBUFDRAW)
1165 backdrawview3d(0);
1168 /* samples a single pixel (copied from vpaint) */
1169 unsigned int sample_backbuf(int x, int y)
1171 unsigned int col;
1173 if(x>=curarea->winx || y>=curarea->winy) return 0;
1174 x+= curarea->winrct.xmin;
1175 y+= curarea->winrct.ymin;
1177 check_backbuf(); // actually not needed for apple
1179 #ifdef __APPLE__
1180 glReadBuffer(GL_AUX0);
1181 #endif
1182 glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
1183 glReadBuffer(GL_BACK);
1185 if(G.order==B_ENDIAN) SWITCH_INT(col);
1187 return framebuffer_to_index(col);
1190 /* reads full rect, converts indices */
1191 ImBuf *read_backbuf(short xmin, short ymin, short xmax, short ymax)
1193 unsigned int *dr, *rd;
1194 struct ImBuf *ibuf, *ibuf1;
1195 int a;
1196 short xminc, yminc, xmaxc, ymaxc, xs, ys;
1198 /* clip */
1199 if(xmin<0) xminc= 0; else xminc= xmin;
1200 if(xmax>=curarea->winx) xmaxc= curarea->winx-1; else xmaxc= xmax;
1201 if(xminc > xmaxc) return NULL;
1203 if(ymin<0) yminc= 0; else yminc= ymin;
1204 if(ymax>=curarea->winy) ymaxc= curarea->winy-1; else ymaxc= ymax;
1205 if(yminc > ymaxc) return NULL;
1207 ibuf= IMB_allocImBuf((xmaxc-xminc+1), (ymaxc-yminc+1), 32, IB_rect,0);
1209 check_backbuf(); // actually not needed for apple
1211 #ifdef __APPLE__
1212 glReadBuffer(GL_AUX0);
1213 #endif
1214 glReadPixels(curarea->winrct.xmin+xminc, curarea->winrct.ymin+yminc, (xmaxc-xminc+1), (ymaxc-yminc+1), GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
1215 glReadBuffer(GL_BACK);
1217 if(G.order==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
1219 a= (xmaxc-xminc+1)*(ymaxc-yminc+1);
1220 dr= ibuf->rect;
1221 while(a--) {
1222 if(*dr) *dr= framebuffer_to_index(*dr);
1223 dr++;
1226 /* put clipped result back, if needed */
1227 if(xminc==xmin && xmaxc==xmax && yminc==ymin && ymaxc==ymax)
1228 return ibuf;
1230 ibuf1= IMB_allocImBuf( (xmax-xmin+1),(ymax-ymin+1),32,IB_rect,0);
1231 rd= ibuf->rect;
1232 dr= ibuf1->rect;
1234 for(ys= ymin; ys<=ymax; ys++) {
1235 for(xs= xmin; xs<=xmax; xs++, dr++) {
1236 if( xs>=xminc && xs<=xmaxc && ys>=yminc && ys<=ymaxc) {
1237 *dr= *rd;
1238 rd++;
1242 IMB_freeImBuf(ibuf);
1243 return ibuf1;
1246 /* smart function to sample a rect spiralling outside, nice for backbuf selection */
1247 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))
1249 struct ImBuf *buf;
1250 unsigned int *bufmin, *bufmax, *tbuf;
1251 int minx, miny;
1252 int a, b, rc, nr, amount, dirvec[4][2];
1253 int distance=0;
1254 unsigned int index = 0;
1255 short indexok = 0;
1257 amount= (size-1)/2;
1259 minx = mval[0]-(amount+1);
1260 miny = mval[1]-(amount+1);
1261 buf = read_backbuf(minx, miny, minx+size-1, miny+size-1);
1262 if (!buf) return 0;
1264 rc= 0;
1266 dirvec[0][0]= 1; dirvec[0][1]= 0;
1267 dirvec[1][0]= 0; dirvec[1][1]= -size;
1268 dirvec[2][0]= -1; dirvec[2][1]= 0;
1269 dirvec[3][0]= 0; dirvec[3][1]= size;
1271 bufmin = buf->rect;
1272 tbuf = buf->rect;
1273 bufmax = buf->rect + size*size;
1274 tbuf+= amount*size+ amount;
1276 for(nr=1; nr<=size; nr++) {
1278 for(a=0; a<2; a++) {
1279 for(b=0; b<nr; b++, distance++) {
1280 if (*tbuf && *tbuf>=min && *tbuf<max) { //we got a hit
1281 if(strict){
1282 indexok = indextest(*tbuf - min+1);
1283 if(indexok){
1284 *dist= (short) sqrt( (float)distance );
1285 index = *tbuf - min+1;
1286 goto exit;
1289 else{
1290 *dist= (short) sqrt( (float)distance ); // XXX, this distance is wrong -
1291 index = *tbuf - min+1; // messy yah, but indices start at 1
1292 goto exit;
1296 tbuf+= (dirvec[rc][0]+dirvec[rc][1]);
1298 if(tbuf<bufmin || tbuf>=bufmax) {
1299 goto exit;
1302 rc++;
1303 rc &= 3;
1307 exit:
1308 IMB_freeImBuf(buf);
1309 return index;
1312 void drawname(Object *ob)
1314 cpack(0x404040);
1315 glRasterPos3f(0.0, 0.0, 0.0);
1317 BMF_DrawString(G.font, " ");
1318 BMF_DrawString(G.font, ob->id.name+2);
1322 static void draw_selected_name(Object *ob)
1324 char info[128];
1325 short offset=30;
1327 if(ob->type==OB_ARMATURE) {
1328 bArmature *arm= ob->data;
1329 char *name= NULL;
1331 if(ob==G.obedit) {
1332 EditBone *ebo;
1333 for (ebo=G.edbo.first; ebo; ebo=ebo->next){
1334 if ((ebo->flag & BONE_ACTIVE) && (ebo->layer & arm->layer)) {
1335 name= ebo->name;
1336 break;
1340 else if(ob->pose && (ob->flag & OB_POSEMODE)) {
1341 bPoseChannel *pchan;
1342 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1343 if((pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer)) {
1344 name= pchan->name;
1345 break;
1349 if(name)
1350 sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, name);
1351 else
1352 sprintf(info, "(%d) %s", CFRA, ob->id.name+2);
1354 else if(ob->type==OB_MESH) {
1355 Key *key= NULL;
1356 KeyBlock *kb = NULL;
1357 char shapes[75];
1359 shapes[0] = 0;
1360 key = ob_get_key(ob);
1361 if(key){
1362 kb = BLI_findlink(&key->block, ob->shapenr-1);
1363 if(kb){
1364 sprintf(shapes, ": %s ", kb->name);
1365 if(ob->shapeflag == OB_SHAPE_LOCK){
1366 sprintf(shapes, "%s (Pinned)",shapes);
1370 sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, shapes);
1372 else sprintf(info, "(%d) %s", CFRA, ob->id.name+2);
1374 BIF_ThemeColor(TH_TEXT_HI);
1375 if (U.uiflag & USER_SHOW_ROTVIEWICON)
1376 offset = 14 + (U.rvisize * 2);
1378 glRasterPos2i(offset, 10);
1379 BMF_DrawString(G.fonts, info);
1383 /* Draw a live substitute of the view icon, which is always shown */
1384 static void draw_view_axis(void)
1386 const float k = U.rvisize; /* axis size */
1387 const float toll = 0.5; /* used to see when view is quasi-orthogonal */
1388 const float start = k + 1.0; /* axis center in screen coordinates, x=y */
1389 float ydisp = 0.0; /* vertical displacement to allow obj info text */
1390 char *cam_name, info[128];
1391 short offset;
1393 if((G.scene) && (G.scene->camera))
1394 cam_name= G.scene->camera->id.name+2;
1395 else
1396 cam_name= NULL;
1398 /* rvibright ranges approx. from original axis icon color to gizmo color */
1399 float bright = U.rvibright / 15.0f;
1401 unsigned char col[3];
1402 unsigned char gridcol[3];
1403 float colf[3];
1405 float vec[4];
1406 float dx, dy;
1407 float h, s, v;
1409 BIF_GetThemeColor3ubv(TH_GRID, (char *)gridcol);
1411 /* X */
1412 vec[0] = vec[3] = 1;
1413 vec[1] = vec[2] = 0;
1414 QuatMulVecf(G.vd->viewquat, vec);
1416 make_axis_color((char *)gridcol, (char *)col, 'x');
1417 rgb_to_hsv(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, &h, &s, &v);
1418 s = s<0.5 ? s+0.5 : 1.0;
1419 v = 0.3;
1420 v = (v<1.0-(bright) ? v+bright : 1.0);
1421 hsv_to_rgb(h, s, v, colf, colf+1, colf+2);
1422 glColor3fv(colf);
1424 dx = vec[0] * k;
1425 dy = vec[1] * k;
1426 fdrawline(start, start + ydisp, start + dx, start + dy + ydisp);
1427 if (fabs(dx) > toll || fabs(dy) > toll) {
1428 glRasterPos2i(start + dx + 2, start + dy + ydisp + 2);
1429 BMF_DrawString(G.fonts, "x");
1432 /* Y */
1433 vec[1] = vec[3] = 1;
1434 vec[0] = vec[2] = 0;
1435 QuatMulVecf(G.vd->viewquat, vec);
1437 make_axis_color((char *)gridcol, (char *)col, 'y');
1438 rgb_to_hsv(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, &h, &s, &v);
1439 s = s<0.5 ? s+0.5 : 1.0;
1440 v = 0.3;
1441 v = (v<1.0-(bright) ? v+bright : 1.0);
1442 hsv_to_rgb(h, s, v, colf, colf+1, colf+2);
1443 glColor3fv(colf);
1445 dx = vec[0] * k;
1446 dy = vec[1] * k;
1447 fdrawline(start, start + ydisp, start + dx, start + dy + ydisp);
1448 if (fabs(dx) > toll || fabs(dy) > toll) {
1449 glRasterPos2i(start + dx + 2, start + dy + ydisp + 2);
1450 BMF_DrawString(G.fonts, "y");
1453 /* Z */
1454 vec[2] = vec[3] = 1;
1455 vec[1] = vec[0] = 0;
1456 QuatMulVecf(G.vd->viewquat, vec);
1458 make_axis_color((char *)gridcol, (char *)col, 'z');
1459 rgb_to_hsv(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, &h, &s, &v);
1460 s = s<0.5 ? s+0.5 : 1.0;
1461 v = 0.5;
1462 v = (v<1.0-(bright) ? v+bright : 1.0);
1463 hsv_to_rgb(h, s, v, colf, colf+1, colf+2);
1464 glColor3fv(colf);
1466 dx = vec[0] * k;
1467 dy = vec[1] * k;
1468 fdrawline(start, start + ydisp, start + dx, start + dy + ydisp);
1469 if (fabs(dx) > toll || fabs(dy) > toll) {
1470 glRasterPos2i(start + dx + 2, start + dy + ydisp + 2);
1471 BMF_DrawString(G.fonts, "z");
1474 if((G.show_cam) && (cam_name)) {
1475 BIF_ThemeColor(TH_TEXT_HI);
1476 sprintf(info, "CA: %s", cam_name);
1477 offset= (G.vd->area->winx-30) - (strlen (cam_name) * 12);
1478 glRasterPos2i(offset, 10);
1479 BMF_DrawString(G.fonts, info);
1484 static void draw_view_icon(void)
1486 BIFIconID icon;
1488 if(G.vd->view==7) icon= ICON_AXIS_TOP;
1489 else if(G.vd->view==1) icon= ICON_AXIS_FRONT;
1490 else if(G.vd->view==3) icon= ICON_AXIS_SIDE;
1491 else return ;
1493 glEnable(GL_BLEND);
1494 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1496 BIF_icon_draw(5.0, 5.0, icon);
1498 glDisable(GL_BLEND);
1501 static void draw_viewport_name(ScrArea *sa)
1503 char *name = NULL;
1504 char *printable = NULL;
1506 switch(G.vd->view) {
1507 case 1:
1508 if (G.vd->persp & V3D_PERSP_DO_3D_PERSP)
1509 name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Back Persp" : "Front Persp";
1510 else
1511 name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Back Ortho" : "Front Ortho";
1512 break;
1513 case 3:
1514 if (G.vd->persp & V3D_PERSP_DO_3D_PERSP)
1515 name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Left Persp" : "Right Persp";
1516 else
1517 name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Left Ortho" : "Right Ortho";
1518 break;
1519 case 7:
1520 if (G.vd->persp & V3D_PERSP_DO_3D_PERSP)
1521 name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Bottom Persp" : "Top Persp";
1522 else
1523 name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Bottom Ortho" : "Top Ortho";
1524 break;
1525 default:
1526 if(G.vd->persp==V3D_PERSP_USE_THE_CAMERA) {
1527 if (G.vd->camera->type == OB_CAMERA) {
1528 Camera *cam;
1529 cam = G.vd->camera->data;
1530 name = (cam->type != CAM_ORTHO) ? "Camera Persp" : "Camera Ortho";
1531 } else {
1532 name = "Object as Camera";
1534 } else {
1535 name = (G.vd->persp & V3D_PERSP_DO_3D_PERSP) ? "User Persp" : "User Ortho";
1539 /* Easy sync of tests to clean up the string allocation */
1540 if (G.vd->localview) {
1541 printable = malloc(strlen(name) + strlen(" (Local)_")); /* '_' gives space for '\0' */
1542 strcpy(printable, name);
1543 strcat(printable, " (Local)");
1544 } else {
1545 printable = name;
1548 if (printable) {
1549 BIF_ThemeColor(TH_TEXT_HI);
1550 glRasterPos2i(10, sa->winy-20);
1551 BMF_DrawString(G.fonts, printable);
1554 if (G.vd->localview) {
1555 free(printable);
1559 /* ******************* view3d space & buttons ************** */
1562 /* temporal struct for storing transform properties */
1563 typedef struct {
1564 float ob_eul[4]; // used for quat too....
1565 float ob_scale[3]; // need temp space due to linked values
1566 float ob_dims[3];
1567 short link_scale;
1568 float ve_median[5];
1569 int curdef;
1570 float *defweightp;
1571 } TransformProperties;
1573 /* is used for both read and write... */
1574 static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim)
1576 EditMesh *em = G.editMesh;
1577 EditVert *eve, *evedef=NULL;
1578 EditEdge *eed;
1579 MDeformVert *dvert=NULL;
1580 TransformProperties *tfp= G.vd->properties_storage;
1581 float median[5], ve_median[5];
1582 int tot, totw, totweight, totedge;
1583 char defstr[320];
1585 median[0]= median[1]= median[2]= median[3]= median[4]= 0.0;
1586 tot= totw= totweight= totedge= 0;
1587 defstr[0]= 0;
1589 if(ob->type==OB_MESH) {
1590 eve= em->verts.first;
1591 while(eve) {
1592 if(eve->f & 1) {
1593 evedef= eve;
1594 tot++;
1595 VecAddf(median, median, eve->co);
1597 eve= eve->next;
1599 eed= em->edges.first;
1600 while(eed) {
1601 if((eed->f & SELECT)) {
1602 totedge++;
1603 median[3]+= eed->crease;
1605 eed= eed->next;
1608 /* check for defgroups */
1609 if(evedef)
1610 dvert= CustomData_em_get(&em->vdata, evedef->data, CD_MDEFORMVERT);
1611 if(tot==1 && dvert && dvert->totweight) {
1612 bDeformGroup *dg;
1613 int i, max=1, init=1;
1614 char str[320];
1616 for (i=0; i<dvert->totweight; i++){
1617 dg = BLI_findlink (&ob->defbase, dvert->dw[i].def_nr);
1618 if(dg) {
1619 max+= snprintf(str, sizeof(str), "%s %%x%d|", dg->name, dvert->dw[i].def_nr);
1620 if(max<320) strcat(defstr, str);
1622 else printf("oh no!\n");
1623 if(tfp->curdef==dvert->dw[i].def_nr) {
1624 init= 0;
1625 tfp->defweightp= &dvert->dw[i].weight;
1629 if(init) { // needs new initialized
1630 tfp->curdef= dvert->dw[0].def_nr;
1631 tfp->defweightp= &dvert->dw[0].weight;
1635 else if(ob->type==OB_CURVE || ob->type==OB_SURF) {
1636 extern ListBase editNurb; /* editcurve.c */
1637 Nurb *nu;
1638 BPoint *bp;
1639 BezTriple *bezt;
1640 int a;
1642 nu= editNurb.first;
1643 while(nu) {
1644 if((nu->type & 7)==CU_BEZIER) {
1645 bezt= nu->bezt;
1646 a= nu->pntsu;
1647 while(a--) {
1648 if(bezt->f2 & 1) {
1649 VecAddf(median, median, bezt->vec[1]);
1650 tot++;
1651 median[4]+= bezt->weight;
1652 totweight++;
1654 else {
1655 if(bezt->f1 & 1) {
1656 VecAddf(median, median, bezt->vec[0]);
1657 tot++;
1659 if(bezt->f3 & 1) {
1660 VecAddf(median, median, bezt->vec[2]);
1661 tot++;
1664 bezt++;
1667 else {
1668 bp= nu->bp;
1669 a= nu->pntsu*nu->pntsv;
1670 while(a--) {
1671 if(bp->f1 & 1) {
1672 VecAddf(median, median, bp->vec);
1673 median[3]+= bp->vec[3];
1674 totw++;
1675 tot++;
1676 median[4]+= bp->weight;
1677 totweight++;
1679 bp++;
1682 nu= nu->next;
1685 else if(ob->type==OB_LATTICE) {
1686 BPoint *bp;
1687 int a;
1689 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1690 bp= editLatt->def;
1691 while(a--) {
1692 if(bp->f1 & SELECT) {
1693 VecAddf(median, median, bp->vec);
1694 tot++;
1695 median[4]+= bp->weight;
1696 totweight++;
1698 bp++;
1702 if(tot==0) return;
1704 median[0] /= (float)tot;
1705 median[1] /= (float)tot;
1706 median[2] /= (float)tot;
1707 if(totedge) median[3] /= (float)totedge;
1708 else if(totw) median[3] /= (float)totw;
1709 if(totweight) median[4] /= (float)totweight;
1711 if(G.vd->flag & V3D_GLOBAL_STATS)
1712 Mat4MulVecfl(ob->obmat, median);
1714 if(block) { // buttons
1716 uiBlockBeginAlign(block);
1717 if((ob->parent) && (ob->partype == PARBONE)) {
1718 uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, REDRAWVIEW3D, "Global", 160, 135, 70, 19, &G.vd->flag, 0, 0, 0, 0, "Displays global values");
1719 uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, REDRAWVIEW3D, "Local", 230, 135, 70, 19, &G.vd->flag, 0, 0, 0, 0, "Displays local values");
1721 else {
1722 uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, REDRAWVIEW3D, "Global", 160, 150, 70, 19, &G.vd->flag, 0, 0, 0, 0, "Displays global values");
1723 uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, REDRAWVIEW3D, "Local", 230, 150, 70, 19, &G.vd->flag, 0, 0, 0, 0, "Displays local values");
1726 memcpy(tfp->ve_median, median, sizeof(tfp->ve_median));
1728 uiBlockBeginAlign(block);
1729 if(tot==1) {
1730 uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex X:", 10, 110, 290, 19, &(tfp->ve_median[0]), -lim, lim, 10, 3, "");
1731 uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex Y:", 10, 90, 290, 19, &(tfp->ve_median[1]), -lim, lim, 10, 3, "");
1732 uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex Z:", 10, 70, 290, 19, &(tfp->ve_median[2]), -lim, lim, 10, 3, "");
1733 if(totw==1)
1734 uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex W:", 10, 50, 290, 19, &(tfp->ve_median[3]), 0.01, 100.0, 10, 3, "");
1735 uiBlockEndAlign(block);
1737 if(defstr[0]) {
1738 uiDefBut(block, LABEL, 1, "Vertex Deform Groups", 10, 40, 290, 20, NULL, 0.0, 0.0, 0, 0, "");
1740 uiBlockBeginAlign(block);
1741 uiDefButF(block, NUM, B_NOP, "Weight:", 10, 20, 150, 19, tfp->defweightp, 0.0f, 1.0f, 10, 3, "Weight value");
1742 uiDefButI(block, MENU, REDRAWVIEW3D, defstr, 160, 20, 140, 19, &tfp->curdef, 0.0, 0.0, 0, 0, "Current Vertex Group");
1743 uiBlockEndAlign(block);
1745 else if(totweight)
1746 uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 10, 20, 290, 19, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, "");
1749 else {
1750 uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median X:", 10, 110, 290, 19, &(tfp->ve_median[0]), -lim, lim, 10, 3, "");
1751 uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median Y:", 10, 90, 290, 19, &(tfp->ve_median[1]), -lim, lim, 10, 3, "");
1752 uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median Z:", 10, 70, 290, 19, &(tfp->ve_median[2]), -lim, lim, 10, 3, "");
1753 if(totw==tot)
1754 uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median W:", 10, 50, 290, 19, &(tfp->ve_median[3]), 0.01, 100.0, 10, 3, "");
1755 uiBlockEndAlign(block);
1756 if(totweight)
1757 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");
1760 if(totedge==1)
1761 uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Crease W:", 10, 30, 290, 19, &(tfp->ve_median[3]), 0.0, 1.0, 10, 3, "");
1762 else if(totedge>1)
1763 uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median Crease W:", 10, 30, 290, 19, &(tfp->ve_median[3]), 0.0, 1.0, 10, 3, "");
1766 else { // apply
1767 memcpy(ve_median, tfp->ve_median, sizeof(tfp->ve_median));
1769 if(G.vd->flag & V3D_GLOBAL_STATS) {
1770 Mat4Invert(ob->imat, ob->obmat);
1771 Mat4MulVecfl(ob->imat, median);
1772 Mat4MulVecfl(ob->imat, ve_median);
1774 VecSubf(median, ve_median, median);
1775 median[3]= ve_median[3]-median[3];
1776 median[4]= ve_median[4]-median[4];
1778 if(ob->type==OB_MESH) {
1780 eve= em->verts.first;
1781 while(eve) {
1782 if(eve->f & 1) {
1783 VecAddf(eve->co, eve->co, median);
1785 eve= eve->next;
1788 for(eed= em->edges.first; eed; eed= eed->next) {
1789 if(eed->f & SELECT) {
1790 /* ensure the median can be set to zero or one */
1791 if(ve_median[3]==0.0f) eed->crease= 0.0f;
1792 else if(ve_median[3]==1.0f) eed->crease= 1.0f;
1793 else {
1794 eed->crease+= median[3];
1795 CLAMP(eed->crease, 0.0, 1.0);
1800 recalc_editnormals();
1802 else if(ob->type==OB_CURVE || ob->type==OB_SURF) {
1803 extern ListBase editNurb; /* editcurve.c */
1804 Nurb *nu;
1805 BPoint *bp;
1806 BezTriple *bezt;
1807 int a;
1809 nu= editNurb.first;
1810 while(nu) {
1811 if((nu->type & 7)==1) {
1812 bezt= nu->bezt;
1813 a= nu->pntsu;
1814 while(a--) {
1815 if(bezt->f2 & 1) {
1816 VecAddf(bezt->vec[0], bezt->vec[0], median);
1817 VecAddf(bezt->vec[1], bezt->vec[1], median);
1818 VecAddf(bezt->vec[2], bezt->vec[2], median);
1819 bezt->weight+= median[4];
1821 else {
1822 if(bezt->f1 & 1) {
1823 VecAddf(bezt->vec[0], bezt->vec[0], median);
1825 if(bezt->f3 & 1) {
1826 VecAddf(bezt->vec[2], bezt->vec[2], median);
1829 bezt++;
1832 else {
1833 bp= nu->bp;
1834 a= nu->pntsu*nu->pntsv;
1835 while(a--) {
1836 if(bp->f1 & 1) {
1837 VecAddf(bp->vec, bp->vec, median);
1838 bp->vec[3]+= median[3];
1839 bp->weight+= median[4];
1841 bp++;
1844 test2DNurb(nu);
1845 testhandlesNurb(nu); /* test for bezier too */
1847 nu= nu->next;
1850 else if(ob->type==OB_LATTICE) {
1851 BPoint *bp;
1852 int a;
1854 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1855 bp= editLatt->def;
1856 while(a--) {
1857 if(bp->f1 & SELECT) {
1858 VecAddf(bp->vec, bp->vec, median);
1859 bp->weight+= median[4];
1861 bp++;
1865 BIF_undo_push("Transform properties");
1869 /* assumes armature active */
1870 static void validate_bonebutton_cb(void *bonev, void *namev)
1872 Object *ob= OBACT;
1874 if(ob && ob->type==OB_ARMATURE) {
1875 Bone *bone= bonev;
1876 char oldname[32], newname[32];
1878 /* need to be on the stack */
1879 BLI_strncpy(newname, bone->name, 32);
1880 BLI_strncpy(oldname, (char *)namev, 32);
1881 /* restore */
1882 BLI_strncpy(bone->name, oldname, 32);
1884 armature_bone_rename(ob->data, oldname, newname); // editarmature.c
1885 allqueue(REDRAWALL, 0);
1890 static void v3d_posearmature_buts(uiBlock *block, Object *ob, float lim)
1892 uiBut *but;
1893 bArmature *arm;
1894 bPoseChannel *pchan;
1895 Bone *bone= NULL;
1896 TransformProperties *tfp= G.vd->properties_storage;
1898 arm = get_armature(OBACT);
1899 if (!arm || !ob->pose) return;
1901 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1902 bone = pchan->bone;
1903 if(bone && (bone->flag & BONE_ACTIVE) && (bone->layer & arm->layer))
1904 break;
1906 if (!pchan || !bone) return;
1908 if((ob->parent) && (ob->partype == PARBONE))
1909 but= uiDefBut (block, TEX, B_DIFF, "Bone:", 160, 130, 140, 19, bone->name, 1, 31, 0, 0, "");
1910 else
1911 but= uiDefBut(block, TEX, B_DIFF, "Bone:", 160, 140, 140, 19, bone->name, 1, 31, 0, 0, "");
1912 uiButSetFunc(but, validate_bonebutton_cb, bone, NULL);
1914 QuatToEul(pchan->quat, tfp->ob_eul);
1915 tfp->ob_eul[0]*= 180.0/M_PI;
1916 tfp->ob_eul[1]*= 180.0/M_PI;
1917 tfp->ob_eul[2]*= 180.0/M_PI;
1919 uiBlockBeginAlign(block);
1920 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");
1921 uiDefButF(block, NUM, B_ARMATUREPANEL2, "LocX:", 30, 140, 120, 19, pchan->loc, -lim, lim, 100, 3, "");
1922 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");
1923 uiDefButF(block, NUM, B_ARMATUREPANEL2, "LocY:", 30, 120, 120, 19, pchan->loc+1, -lim, lim, 100, 3, "");
1924 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");
1925 uiDefButF(block, NUM, B_ARMATUREPANEL2, "LocZ:", 30, 100, 120, 19, pchan->loc+2, -lim, lim, 100, 3, "");
1927 uiBlockBeginAlign(block);
1928 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");
1929 uiDefButF(block, NUM, B_ARMATUREPANEL3, "RotX:", 30, 70, 120, 19, tfp->ob_eul, -1000.0, 1000.0, 100, 3, "");
1930 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");
1931 uiDefButF(block, NUM, B_ARMATUREPANEL3, "RotY:", 30, 50, 120, 19, tfp->ob_eul+1, -1000.0, 1000.0, 100, 3, "");
1932 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");
1933 uiDefButF(block, NUM, B_ARMATUREPANEL3, "RotZ:", 30, 30, 120, 19, tfp->ob_eul+2, -1000.0, 1000.0, 100, 3, "");
1935 uiBlockBeginAlign(block);
1936 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");
1937 uiDefButF(block, NUM, B_ARMATUREPANEL2, "ScaleX:", 180, 70, 120, 19, pchan->size, -lim, lim, 10, 3, "");
1938 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");
1939 uiDefButF(block, NUM, B_ARMATUREPANEL2, "ScaleY:", 180, 50, 120, 19, pchan->size+1, -lim, lim, 10, 3, "");
1940 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");
1941 uiDefButF(block, NUM, B_ARMATUREPANEL2, "ScaleZ:", 180, 30, 120, 19, pchan->size+2, -lim, lim, 10, 3, "");
1942 uiBlockEndAlign(block);
1945 static void v3d_editarmature_buts(uiBlock *block, Object *ob, float lim)
1947 bArmature *arm= G.obedit->data;
1948 EditBone *ebone;
1949 uiBut *but;
1950 TransformProperties *tfp= G.vd->properties_storage;
1952 ebone= G.edbo.first;
1954 for (ebone = G.edbo.first; ebone; ebone=ebone->next){
1955 if ((ebone->flag & BONE_ACTIVE) && (ebone->layer & arm->layer))
1956 break;
1959 if (!ebone)
1960 return;
1962 if((ob->parent) && (ob->partype == PARBONE))
1963 but= uiDefBut(block, TEX, B_DIFF, "Bone:", 160, 130, 140, 19, ebone->name, 1, 31, 0, 0, "");
1964 else
1965 but= uiDefBut(block, TEX, B_DIFF, "Bone:", 160, 150, 140, 19, ebone->name, 1, 31, 0, 0, "");
1966 uiButSetFunc(but, validate_editbonebutton_cb, ebone, NULL);
1968 uiBlockBeginAlign(block);
1969 uiDefButF(block, NUM, B_ARMATUREPANEL1, "RootX:", 10, 70, 140, 19, ebone->head, -lim, lim, 10, 3, "");
1970 uiDefButF(block, NUM, B_ARMATUREPANEL1, "RootY:", 10, 50, 140, 19, ebone->head+1, -lim, lim, 10, 3, "");
1971 uiDefButF(block, NUM, B_ARMATUREPANEL1, "RootZ:", 10, 30, 140, 19, ebone->head+2, -lim, lim, 10, 3, "");
1972 uiBlockBeginAlign(block);
1973 uiDefButF(block, NUM, B_ARMATUREPANEL1, "TipX:", 160, 70, 140, 19, ebone->tail, -lim, lim, 10, 3, "");
1974 uiDefButF(block, NUM, B_ARMATUREPANEL1, "TipY:", 160, 50, 140, 19, ebone->tail+1, -lim, lim, 10, 3, "");
1975 uiDefButF(block, NUM, B_ARMATUREPANEL1, "TipZ:", 160, 30, 140, 19, ebone->tail+2, -lim, lim, 10, 3, "");
1976 uiBlockEndAlign(block);
1977 tfp->ob_eul[0]= 180.0*ebone->roll/M_PI;
1978 uiDefIconButBitI(block, ICONTOG, BONE_LOCK_ROLL, REDRAWVIEW3D, ICON_UNLOCKED, 10,100,20,19, &(ebone->flag), 0, 0, 0, 0, "Protects roll value from being Recalculate");
1979 uiDefButF(block, NUM, B_ARMATUREPANEL1, "Roll:", 30, 100, 120, 19, tfp->ob_eul, -lim, lim, 1000, 3, "");
1983 uiBlockBeginAlign(block);
1984 uiDefButF(block, NUM, B_ARMATUREPANEL1, "TipRadius:", 10, 150, 140, 19, &ebone->rad_tail, 0, lim, 10, 3, "");
1985 if (ebone->parent && ebone->flag & BONE_CONNECTED )
1986 uiDefButF(block, NUM, B_ARMATUREPANEL1, "HeadRadius:", 10, 130, 140, 19, &ebone->parent->rad_tail, 0, lim, 10, 3, "");
1987 else
1988 uiDefButF(block, NUM, B_ARMATUREPANEL1, "HeadRadius:", 10, 130, 140, 19, &ebone->rad_head, 0, lim, 10, 3, "");
1989 uiBlockEndAlign(block);
1992 static void v3d_editmetaball_buts(uiBlock *block, Object *ob, float lim)
1994 extern MetaElem *lastelem;
1996 if(lastelem) {
1997 uiBlockBeginAlign(block);
1998 uiDefButF(block, NUM, B_RECALCMBALL, "LocX:", 10, 70, 140, 19, &lastelem->x, -lim, lim, 100, 3, "");
1999 uiDefButF(block, NUM, B_RECALCMBALL, "LocY:", 10, 50, 140, 19, &lastelem->y, -lim, lim, 100, 3, "");
2000 uiDefButF(block, NUM, B_RECALCMBALL, "LocZ:", 10, 30, 140, 19, &lastelem->z, -lim, lim, 100, 3, "");
2002 uiBlockBeginAlign(block);
2003 if(lastelem->type!=MB_BALL)
2004 uiDefButF(block, NUM, B_RECALCMBALL, "dx:", 160, 70, 140, 19, &lastelem->expx, 0, lim, 100, 3, "");
2005 if((lastelem->type!=MB_BALL) && (lastelem->type!=MB_TUBE))
2006 uiDefButF(block, NUM, B_RECALCMBALL, "dy:", 160, 50, 140, 19, &lastelem->expy, 0, lim, 100, 3, "");
2007 if((lastelem->type==MB_ELIPSOID) || (lastelem->type==MB_CUBE))
2008 uiDefButF(block, NUM, B_RECALCMBALL, "dz:", 160, 30, 140, 19, &lastelem->expz, 0, lim, 100, 3, "");
2010 uiBlockEndAlign(block);
2012 uiBlockBeginAlign(block);
2013 uiDefButF(block, NUM, B_RECALCMBALL, "Radius:", 10, 120, 140, 19, &lastelem->rad, 0, lim, 100, 3, "Size of the active metaball");
2014 uiDefButF(block, NUM, B_RECALCMBALL, "Stiffness:", 10, 100, 140, 19, &lastelem->s, 0, 10, 100, 3, "Stiffness of the active metaball");
2015 uiBlockEndAlign(block);
2017 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");
2022 void do_viewbuts(unsigned short event)
2024 BoundBox *bb;
2025 View3D *vd;
2026 Object *ob= OBACT;
2027 TransformProperties *tfp= G.vd->properties_storage;
2029 vd= G.vd;
2030 if(vd==NULL) return;
2032 switch(event) {
2034 case B_OBJECTPANEL:
2035 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
2036 allqueue(REDRAWVIEW3D, 1);
2037 break;
2039 case B_OBJECTPANELROT:
2040 if(ob) {
2041 ob->rot[0]= M_PI*tfp->ob_eul[0]/180.0;
2042 ob->rot[1]= M_PI*tfp->ob_eul[1]/180.0;
2043 ob->rot[2]= M_PI*tfp->ob_eul[2]/180.0;
2044 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
2045 allqueue(REDRAWVIEW3D, 1);
2047 break;
2049 case B_OBJECTPANELSCALE:
2050 if(ob) {
2052 /* link scale; figure out which axis changed */
2053 if (tfp->link_scale) {
2054 float ratio, tmp, max = 0.0;
2055 int axis;
2057 axis = 0;
2058 max = fabs(tfp->ob_scale[0] - ob->size[0]);
2059 tmp = fabs(tfp->ob_scale[1] - ob->size[1]);
2060 if (tmp > max) {
2061 axis = 1;
2062 max = tmp;
2064 tmp = fabs(tfp->ob_scale[2] - ob->size[2]);
2065 if (tmp > max) {
2066 axis = 2;
2067 max = tmp;
2070 if (ob->size[axis] != tfp->ob_scale[axis]) {
2071 if (fabs(ob->size[axis]) > FLT_EPSILON) {
2072 ratio = tfp->ob_scale[axis] / ob->size[axis];
2073 ob->size[0] *= ratio;
2074 ob->size[1] *= ratio;
2075 ob->size[2] *= ratio;
2079 else {
2080 VECCOPY(ob->size, tfp->ob_scale);
2083 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
2084 allqueue(REDRAWVIEW3D, 1);
2086 break;
2088 case B_OBJECTPANELDIMS:
2089 bb= object_get_boundbox(ob);
2090 if(bb) {
2091 float old_dims[3], scale[3], ratio, len[3];
2092 int axis;
2094 Mat4ToSize(ob->obmat, scale);
2096 len[0] = bb->vec[4][0] - bb->vec[0][0];
2097 len[1] = bb->vec[2][1] - bb->vec[0][1];
2098 len[2] = bb->vec[1][2] - bb->vec[0][2];
2100 old_dims[0] = fabs(scale[0]) * len[0];
2101 old_dims[1] = fabs(scale[1]) * len[1];
2102 old_dims[2] = fabs(scale[2]) * len[2];
2104 /* for each axis changed */
2105 for (axis = 0; axis<3; axis++) {
2106 if (fabs(old_dims[axis] - tfp->ob_dims[axis]) > 0.0001) {
2107 if (old_dims[axis] > 0.0) {
2108 ratio = tfp->ob_dims[axis] / old_dims[axis];
2109 if (tfp->link_scale) {
2110 ob->size[0] *= ratio;
2111 ob->size[1] *= ratio;
2112 ob->size[2] *= ratio;
2113 break;
2115 else {
2116 ob->size[axis] *= ratio;
2119 else {
2120 if (len[axis] > 0) {
2121 ob->size[axis] = tfp->ob_dims[axis] / len[axis];
2127 /* prevent multiple B_OBJECTPANELDIMS events to keep scaling, cycling with TAB on buttons can cause that */
2128 VECCOPY(tfp->ob_dims, old_dims);
2130 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
2131 allqueue(REDRAWVIEW3D, 1);
2133 break;
2135 case B_OBJECTPANELMEDIAN:
2136 if(ob) {
2137 v3d_editvertex_buts(NULL, ob, 1.0);
2138 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2139 allqueue(REDRAWVIEW3D, 1);
2141 break;
2143 /* note; this case also used for parbone */
2144 case B_OBJECTPANELPARENT:
2145 if(ob) {
2146 if(ob->id.lib || test_parent_loop(ob->parent, ob) )
2147 ob->parent= NULL;
2148 else {
2149 DAG_scene_sort(G.scene);
2150 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
2152 allqueue(REDRAWVIEW3D, 1);
2153 allqueue(REDRAWBUTSOBJECT, 0);
2155 break;
2157 case B_ARMATUREPANEL1:
2159 bArmature *arm= G.obedit->data;
2160 EditBone *ebone, *child;
2162 for (ebone = G.edbo.first; ebone; ebone=ebone->next){
2163 if ((ebone->flag & BONE_ACTIVE) && (ebone->layer & arm->layer))
2164 break;
2166 if (ebone) {
2167 ebone->roll= M_PI*tfp->ob_eul[0]/180.0;
2168 // Update our parent
2169 if (ebone->parent && ebone->flag & BONE_CONNECTED){
2170 VECCOPY (ebone->parent->tail, ebone->head);
2173 // Update our children if necessary
2174 for (child = G.edbo.first; child; child=child->next){
2175 if (child->parent == ebone && (child->flag & BONE_CONNECTED)){
2176 VECCOPY (child->head, ebone->tail);
2179 if(arm->flag & ARM_MIRROR_EDIT) {
2180 EditBone *eboflip= armature_bone_get_mirrored(ebone);
2181 if(eboflip) {
2182 eboflip->roll= -ebone->roll;
2183 eboflip->head[0]= -ebone->head[0];
2184 eboflip->tail[0]= -ebone->tail[0];
2186 // Update our parent
2187 if (eboflip->parent && eboflip->flag & BONE_CONNECTED){
2188 VECCOPY (eboflip->parent->tail, eboflip->head);
2191 // Update our children if necessary
2192 for (child = G.edbo.first; child; child=child->next){
2193 if (child->parent == eboflip && (child->flag & BONE_CONNECTED)){
2194 VECCOPY (child->head, eboflip->tail);
2200 allqueue(REDRAWVIEW3D, 1);
2203 break;
2204 case B_ARMATUREPANEL3: // rotate button on channel
2206 bArmature *arm;
2207 bPoseChannel *pchan;
2208 Bone *bone;
2209 float eul[3];
2211 arm = get_armature(OBACT);
2212 if (!arm || !ob->pose) return;
2214 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
2215 bone = pchan->bone;
2216 if(bone && (bone->flag & BONE_ACTIVE) && (bone->layer & arm->layer))
2217 break;
2219 if (!pchan) return;
2221 /* make a copy to eul[3], to allow TAB on buttons to work */
2222 eul[0]= M_PI*tfp->ob_eul[0]/180.0;
2223 eul[1]= M_PI*tfp->ob_eul[1]/180.0;
2224 eul[2]= M_PI*tfp->ob_eul[2]/180.0;
2225 EulToQuat(eul, pchan->quat);
2227 /* no break, pass on */
2228 case B_ARMATUREPANEL2:
2230 ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
2231 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2232 allqueue(REDRAWVIEW3D, 1);
2234 break;
2238 static void panel_armature_layer_cb (void *lay_v, void *value_v)
2240 short *layer= lay_v;
2241 int value= (int)value_v;
2243 if(*layer==0 || G.qual==0) *layer= value;
2244 allqueue(REDRAWBUTSEDIT, 0);
2245 allqueue(REDRAWACTION, 0);
2246 allqueue(REDRAWNLA, 0);
2249 static void view3d_panel_object(short cntrl) // VIEW3D_HANDLER_OBJECT
2251 uiBlock *block;
2252 uiBut *bt= NULL;
2253 Object *ob= OBACT;
2254 TransformProperties *tfp;
2255 float lim;
2256 static char hexcol[128];
2257 bArmature *arm;
2258 int a;
2260 if(ob==NULL) return;
2262 /* make sure we got storage */
2263 if(G.vd->properties_storage==NULL)
2264 G.vd->properties_storage= MEM_callocN(sizeof(TransformProperties), "TransformProperties");
2265 tfp= G.vd->properties_storage;
2267 block= uiNewBlock(&curarea->uiblocks, "view3d_panel_object", UI_EMBOSS, UI_HELV, curarea->win);
2268 uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
2269 uiSetPanelHandler(VIEW3D_HANDLER_OBJECT); // for close and esc
2271 if(ob->type== OB_ARMATURE) {
2272 if(G.prop_flag & 1) {
2273 if(!uiNewPanel(curarea, block, "Transform Properties", "View3d", 10, 230, 318, 310))
2274 return;
2276 else {
2277 if(!uiNewPanel(curarea, block, "Transform Properties", "View3d", 10, 230, 195, 100))
2278 return;
2281 else {
2282 if(!uiNewPanel(curarea, block, "Transform Properties", "View3d", 10, 230, 318, 204))
2283 return;
2286 uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2288 if(G.prop_flag & 1) {
2289 if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT))
2290 uiBlockSetFlag(block, UI_BLOCK_FRONTBUFFER);
2291 else {
2292 bt= uiDefBut(block, TEX, B_IDNAME, "OB: ", 10, 180, 140, 20, ob->id.name+2, 0.0, 19.0, 0, 0, "");
2293 #ifdef WITH_VERSE
2294 if(ob->vnode) uiButSetFunc(bt, test_and_send_idbutton_cb, ob, ob->id.name);
2295 else uiButSetFunc(bt, test_idbutton_cb, ob->id.name, NULL);
2296 #else
2297 uiButSetFunc(bt, test_idbutton_cb, ob->id.name, NULL);
2298 #endif
2301 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_OBJECTPANELPARENT, "Par:", 160, 180, 140, 20, &ob->parent, "Parent Object");
2302 if((ob->parent) && (ob->partype == PARBONE)) {
2303 if (G.f & G_SCULPTMODE)
2304 uiDefBut(block, TEX, B_OBJECTPANELPARENT, "ParBone:", 310, 180, 140, 20, ob->parsubstr, 0.0, 30.0, 0, 0, "");
2305 else
2306 uiDefBut(block, TEX, B_OBJECTPANELPARENT, "ParBone:", 160, 160, 140, 20, ob->parsubstr, 0.0, 30.0, 0, 0, "");
2308 uiButSetCompleteFunc(bt, autocomplete_bone, (void *)ob->parent);
2310 else {
2311 strcpy(ob->parsubstr, "");
2314 lim= 10000.0f*MAX2(1.0, G.vd->grid);
2316 if(ob==G.obedit) {
2317 if(ob->type==OB_ARMATURE) {
2318 v3d_editarmature_buts(block, ob, lim);
2319 uiDefButS(block, TOG, REDRAWVIEW3D, "Hide Properties", 10, -10, 140, 19, &G.prop_flag, 0, 0, 0, 0, "Don't show transformation properties");
2321 if(ob->type==OB_MBALL) v3d_editmetaball_buts(block, ob, lim);
2322 else v3d_editvertex_buts(block, ob, lim);
2324 else if(ob->flag & OB_POSEMODE) {
2325 v3d_posearmature_buts(block, ob, lim);
2326 uiDefButS(block, TOG, REDRAWVIEW3D, "Hide Properties", 10, -10, 140, 19, &G.prop_flag, 0, 0, 0, 0, "Don't show transformation properties");
2328 else if(G.f & G_WEIGHTPAINT) {
2329 uiNewPanelTitle(block, "Weight Paint Properties");
2330 weight_paint_buttons(block);
2332 else if(G.f & (G_VERTEXPAINT|G_TEXTUREPAINT)) {
2333 extern VPaint Gvp; /* from vpaint */
2334 static float hsv[3], old[3]; // used as temp mem for picker
2335 float *rgb= NULL;
2336 ToolSettings *settings= G.scene->toolsettings;
2338 if(G.f & G_VERTEXPAINT) rgb= &Gvp.r;
2339 else if(settings->imapaint.brush) rgb= settings->imapaint.brush->rgb;
2341 uiNewPanelTitle(block, "Paint Properties");
2342 if (rgb)
2343 /* 'f' is for floating panel */
2344 uiBlockPickerButtons(block, rgb, hsv, old, hexcol, 'f', REDRAWBUTSEDIT);
2346 else if(G.f & G_SCULPTMODE) {
2347 uiNewPanelTitle(block, "Sculpt Properties");
2348 sculptmode_draw_interface_tools(block,10,150);
2349 } else {
2350 BoundBox *bb = NULL;
2352 uiBlockBeginAlign(block);
2353 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");
2354 uiDefButF(block, NUM, B_OBJECTPANEL, "LocX:", 30, 150, 120, 19, &(ob->loc[0]), -lim, lim, 100, 3, "");
2355 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");
2356 uiDefButF(block, NUM, B_OBJECTPANEL, "LocY:", 30, 130, 120, 19, &(ob->loc[1]), -lim, lim, 100, 3, "");
2357 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");
2358 uiDefButF(block, NUM, B_OBJECTPANEL, "LocZ:", 30, 110, 120, 19, &(ob->loc[2]), -lim, lim, 100, 3, "");
2360 tfp->ob_eul[0]= 180.0*ob->rot[0]/M_PI;
2361 tfp->ob_eul[1]= 180.0*ob->rot[1]/M_PI;
2362 tfp->ob_eul[2]= 180.0*ob->rot[2]/M_PI;
2364 uiBlockBeginAlign(block);
2365 if ((ob->parent) && (ob->partype == PARBONE)) {
2366 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");
2367 uiDefButF(block, NUM, B_OBJECTPANELROT, "RotX:", 180, 130, 120, 19, &(tfp->ob_eul[0]), -lim, lim, 1000, 3, "");
2368 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");
2369 uiDefButF(block, NUM, B_OBJECTPANELROT, "RotY:", 180, 110, 120, 19, &(tfp->ob_eul[1]), -lim, lim, 1000, 3, "");
2370 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");
2371 uiDefButF(block, NUM, B_OBJECTPANELROT, "RotZ:", 180, 90, 120, 19, &(tfp->ob_eul[2]), -lim, lim, 1000, 3, "");
2373 else {
2374 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");
2375 uiDefButF(block, NUM, B_OBJECTPANELROT, "RotX:", 180, 150, 120, 19, &(tfp->ob_eul[0]), -lim, lim, 1000, 3, "");
2376 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");
2377 uiDefButF(block, NUM, B_OBJECTPANELROT, "RotY:", 180, 130, 120, 19, &(tfp->ob_eul[1]), -lim, lim, 1000, 3, "");
2378 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");
2379 uiDefButF(block, NUM, B_OBJECTPANELROT, "RotZ:", 180, 110, 120, 19, &(tfp->ob_eul[2]), -lim, lim, 1000, 3, "");
2382 tfp->ob_scale[0]= ob->size[0];
2383 tfp->ob_scale[1]= ob->size[1];
2384 tfp->ob_scale[2]= ob->size[2];
2386 uiBlockBeginAlign(block);
2387 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");
2388 uiDefButF(block, NUM, B_OBJECTPANELSCALE, "ScaleX:", 30, 80, 120, 19, &(tfp->ob_scale[0]), -lim, lim, 10, 3, "");
2389 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");
2390 uiDefButF(block, NUM, B_OBJECTPANELSCALE, "ScaleY:", 30, 60, 120, 19, &(tfp->ob_scale[1]), -lim, lim, 10, 3, "");
2391 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");
2392 uiDefButF(block, NUM, B_OBJECTPANELSCALE, "ScaleZ:", 30, 40, 120, 19, &(tfp->ob_scale[2]), -lim, lim, 10, 3, "");
2393 uiBlockEndAlign(block);
2395 uiDefButS(block, TOG, REDRAWVIEW3D, "Link Scale", 10, 10, 140, 19, &(tfp->link_scale), 0, 1, 0, 0, "Scale values vary proportionally in all directions");
2396 uiDefButS(block, TOG, REDRAWVIEW3D, "Hide Properties", 10, -15, 140, 19, &G.prop_flag, 0, 0, 0, 0, "Don't show transformation properties");
2398 bb= object_get_boundbox(ob);
2399 if (bb) {
2400 float scale[3];
2402 Mat4ToSize(ob->obmat, scale);
2404 tfp->ob_dims[0] = fabs(scale[0]) * (bb->vec[4][0] - bb->vec[0][0]);
2405 tfp->ob_dims[1] = fabs(scale[1]) * (bb->vec[2][1] - bb->vec[0][1]);
2406 tfp->ob_dims[2] = fabs(scale[2]) * (bb->vec[1][2] - bb->vec[0][2]);
2408 uiBlockBeginAlign(block);
2409 if ((ob->parent) && (ob->partype == PARBONE)) {
2410 uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimX:", 160, 60, 140, 19, &(tfp->ob_dims[0]), 0.0, lim, 10, 3, "Manipulate bounding box size");
2411 uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimY:", 160, 40, 140, 19, &(tfp->ob_dims[1]), 0.0, lim, 10, 3, "Manipulate bounding box size");
2412 uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimZ:", 160, 20, 140, 19, &(tfp->ob_dims[2]), 0.0, lim, 10, 3, "Manipulate bounding box size");
2415 else {
2416 uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimX:", 160, 80, 140, 19, &(tfp->ob_dims[0]), 0.0, lim, 10, 3, "Manipulate bounding box size");
2417 uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimY:", 160, 60, 140, 19, &(tfp->ob_dims[1]), 0.0, lim, 10, 3, "Manipulate bounding box size");
2418 uiDefButF(block, NUM, B_OBJECTPANELDIMS, "DimZ:", 160, 40, 140, 19, &(tfp->ob_dims[2]), 0.0, lim, 10, 3, "Manipulate bounding box size");
2421 uiBlockEndAlign(block);
2425 else
2426 uiDefButS(block, TOG, REDRAWVIEW3D, "Show Properties", 10, 170, 140, 19, &G.prop_flag, 0, 1, 0, 0, "Show transformation Properties");
2428 if((ob->type!=OB_ARMATURE) || (G.f & G_SCULPTMODE)) {
2429 uiClearButLock();
2430 return;
2433 arm= ob->data;
2434 if(!(G.prop_flag & 1)) {
2435 uiDefBut(block, LABEL, 0, "Armature Layers:", 10, 150, 150, 19, 0, 0, 0, 0, 0, "");
2437 /* layers */
2438 uiBlockBeginAlign (block);
2439 for(a= 0; a<8; a++) {
2440 bt= uiDefButBitS(block, BUT_TOGDUAL, 1<<a, REDRAWVIEW3D, "", 10 + 19 * a, 130, 19, 19, &arm->layer, 0, 0, 0, 0, "");
2441 uiButSetFunc(bt, panel_armature_layer_cb, &arm->layer, (void *)(1<<a));
2444 uiBlockBeginAlign (block);
2445 for (a = 8; a < 16; a++) {
2446 bt = uiDefButBitS (block, BUT_TOGDUAL, 1<<a, REDRAWVIEW3D, "", 10 + 19 * (a-8), 110, 19, 19, &arm->layer, 0, 0, 0, 0, "");
2447 uiButSetFunc (bt, panel_armature_layer_cb, &arm->layer, (void *)(1<<a));
2450 else {
2451 uiDefBut(block, LABEL, 0, "Armature Layers:", 10, -40, 150, 19, 0, 0, 0, 0, 0, "");
2453 /* layers */
2454 uiBlockBeginAlign (block);
2456 for(a= 0; a<8; a++) {
2457 bt= uiDefButBitS(block, BUT_TOGDUAL, 1<<a, REDRAWVIEW3D, "", 10 + 19 * a, -60, 19, 19, &arm->layer, 0, 0, 0, 0, "");
2458 uiButSetFunc(bt, panel_armature_layer_cb, &arm->layer, (void *)(1<<a));
2461 uiBlockBeginAlign (block);
2462 for (a = 8; a < 16; a++) {
2463 bt = uiDefButBitS (block, BUT_TOGDUAL, 1<<a, REDRAWVIEW3D, "", 10 + 19 * (a-8), -80, 19, 19, &arm->layer, 0, 0, 0, 0, "");
2464 uiButSetFunc (bt, panel_armature_layer_cb, &arm->layer, (void *)(1<<a));
2468 /* quite bad here, but I don't know a better place for copy... */
2469 /* need here to!! */
2470 if(ob->pose)
2471 ob->pose->proxy_layer= arm->layer;
2473 uiBlockEndAlign (block);
2474 uiClearButLock();
2477 static void view3d_panel_background(short cntrl) // VIEW3D_HANDLER_BACKGROUND
2479 uiBlock *block;
2480 View3D *vd;
2482 vd= G.vd;
2484 block= uiNewBlock(&curarea->uiblocks, "view3d_panel_background", UI_EMBOSS, UI_HELV, curarea->win);
2485 uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
2486 uiSetPanelHandler(VIEW3D_HANDLER_BACKGROUND); // for close and esc
2487 if(uiNewPanel(curarea, block, "Background Image", "View3d", 340, 10, 318, 204)==0) return;
2489 if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT)) {
2490 uiBlockSetFlag(block, UI_BLOCK_FRONTBUFFER); // force old style frontbuffer draw
2493 if(vd->flag & V3D_DISPBGPIC) {
2494 if(vd->bgpic==NULL) {
2495 vd->bgpic= MEM_callocN(sizeof(BGpic), "bgpic");
2496 vd->bgpic->size= 5.0;
2497 vd->bgpic->blend= 0.5;
2498 vd->bgpic->iuser.fie_ima= 2;
2499 vd->bgpic->iuser.ok= 1;
2503 if(!(vd->flag & V3D_DISPBGPIC)) {
2504 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 the 3D View");
2505 uiDefBut(block, LABEL, 1, " ", 160, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
2507 else {
2508 uiBlockBeginAlign(block);
2509 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 the 3D View");
2510 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");
2511 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");
2513 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");
2514 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");
2516 uiblock_image_panel(block, &vd->bgpic->ima, &vd->bgpic->iuser, B_REDR, B_REDR);
2521 static void view3d_panel_properties(short cntrl) // VIEW3D_HANDLER_SETTINGS
2523 uiBlock *block;
2524 View3D *vd;
2525 float *curs;
2527 vd= G.vd;
2529 block= uiNewBlock(&curarea->uiblocks, "view3d_panel_properties", UI_EMBOSS, UI_HELV, curarea->win);
2530 uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
2531 uiSetPanelHandler(VIEW3D_HANDLER_PROPERTIES); // for close and esc
2532 if(uiNewPanel(curarea, block, "View Properties", "View3d", 340, 30, 318, 254)==0) return;
2534 /* to force height */
2535 uiNewPanelHeight(block, 264);
2537 if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT)) {
2538 uiBlockSetFlag(block, UI_BLOCK_FRONTBUFFER); // force old style frontbuffer draw
2541 uiDefBut(block, LABEL, 1, "Grid:", 10, 220, 150, 19, NULL, 0.0, 0.0, 0, 0, "");
2542 uiBlockBeginAlign(block);
2543 uiDefButF(block, NUM, REDRAWVIEW3D, "Spacing:", 10, 200, 140, 19, &vd->grid, 0.001, 100.0, 10, 0, "Set the distance between grid lines");
2544 uiDefButS(block, NUM, REDRAWVIEW3D, "Lines:", 10, 180, 140, 19, &vd->gridlines, 0.0, 100.0, 100, 0, "Set the number of grid lines");
2545 uiDefButS(block, NUM, REDRAWVIEW3D, "Divisions:", 10, 160, 140, 19, &vd->gridsubdiv, 0.0, 100.0, 100, 0, "Set the number of grid lines");
2546 uiBlockEndAlign(block);
2548 uiDefBut(block, LABEL, 1, "3D Display:", 160, 220, 150, 19, NULL, 0.0, 0.0, 0, 0, "");
2549 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");
2550 uiDefButBitS(block, TOG, V3D_SHOW_X, REDRAWVIEW3D, "X Axis", 160, 180, 48, 19, &vd->gridflag, 0, 0, 0, 0, "Show the X Axis line");
2551 uiDefButBitS(block, TOG, V3D_SHOW_Y, REDRAWVIEW3D, "Y Axis", 212, 180, 48, 19, &vd->gridflag, 0, 0, 0, 0, "Show the Y Axis line");
2552 uiDefButBitS(block, TOG, V3D_SHOW_Z, REDRAWVIEW3D, "Z Axis", 262, 180, 48, 19, &vd->gridflag, 0, 0, 0, 0, "Show the Z Axis line");
2553 if(vd->gridflag & V3D_USE_F_FOR_FLY)
2554 uiDefButBitS(block, TOG, V3D_USE_F_FOR_FLY, REDRAWVIEW3D, "Use shift+F for Fly", 160, 160, 150, 19, &vd->gridflag, 0, 0, 0, 0, "Use shift+F for enter to fly mode");
2555 else
2556 uiDefButBitS(block, TOG, V3D_USE_F_FOR_FLY, REDRAWVIEW3D, "Use F for Fly", 160, 160, 150, 19, &vd->gridflag, 0, 0, 0, 0, "Use F for enter to fly mode");
2557 uiDefBut(block, LABEL, 1, "View Camera:", 10, 140, 140, 19, NULL, 0.0, 0.0, 0, 0, "");
2559 uiDefButF(block, NUM, REDRAWVIEW3D, "Lens:", 10, 120, 140, 19, &vd->lens, 10.0, 120.0, 100, 0, "The lens angle in perspective view");
2560 uiBlockBeginAlign(block);
2561 uiDefButF(block, NUM, REDRAWVIEW3D, "Clip Start:", 10, 101, 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)");
2562 uiDefButF(block, NUM, REDRAWVIEW3D, "Clip End:", 10, 82, 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)");
2563 uiDefButS(block, TOG, 1, "Show Camera Name", 10, 56, 140, 19, &G.show_cam, 0, 1, 0, 1, "Show the name of the active camera");
2564 uiBlockEndAlign(block);
2566 uiDefBut(block, LABEL, 1, "3D Cursor:", 160, 140, 140, 19, NULL, 0.0, 0.0, 0, 0, "");
2568 uiBlockBeginAlign(block);
2569 curs= give_cursor();
2570 uiDefButF(block, NUM, REDRAWVIEW3D, "X:", 160, 120, 150, 19, curs, -10000.0*vd->grid, 10000.0*vd->grid, 10, 0, "X co-ordinate of the 3D cursor");
2571 uiDefButF(block, NUM, REDRAWVIEW3D, "Y:", 160, 101, 150, 19, curs+1, -10000.0*vd->grid, 10000.0*vd->grid, 10, 0, "Y co-ordinate of the 3D cursor");
2572 uiDefButF(block, NUM, REDRAWVIEW3D, "Z:", 160, 82, 150, 19, curs+2, -10000.0*vd->grid, 10000.0*vd->grid, 10, 0, "Z co-ordinate of the 3D cursor");
2573 uiBlockEndAlign(block);
2575 uiDefBut(block, LABEL, 1, "Display:", 10, 30, 150, 19, NULL, 0.0, 0.0, 0, 0, "");
2577 uiBlockBeginAlign(block);
2578 uiDefButBitS(block, TOG, V3D_SELECT_OUTLINE, REDRAWVIEW3D, "Outline Selected", 10, 10, 140, 19, &vd->flag, 0, 0, 0, 0, "Highlight selected objects with an outline, in Solid, Shaded or Textured viewport shading modes");
2579 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");
2580 uiDefButBitS(block, TOGN, V3D_HIDE_HELPLINES, REDRAWVIEW3D, "Relationship Lines", 10, -30, 140, 19, &vd->flag, 0, 0, 0, 0, "Draw dashed lines indicating Parent, Constraint, or Hook relationships");
2581 uiBlockEndAlign(block);
2583 uiDefBut(block, LABEL, 1, "View Locking:", 160, 50, 150, 19, NULL, 0.0, 0.0, 0, 0, "");
2584 uiBlockBeginAlign(block);
2585 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, REDRAWVIEW3D, "Object:", 160, 30, 140, 19, &vd->ob_centre, "Lock view to center always on this Object");
2586 uiDefBut(block, TEX, REDRAWVIEW3D, "Bone:", 160, 10, 140, 19, vd->ob_centre_bone, 1, 31, 0, 0, "If view locked to Object, use this Bone to lock to view to");
2590 static void view3d_panel_preview(ScrArea *sa, short cntrl) // VIEW3D_HANDLER_PREVIEW
2592 uiBlock *block;
2593 View3D *v3d= sa->spacedata.first;
2594 int ofsx, ofsy;
2596 block= uiNewBlock(&sa->uiblocks, "view3d_panel_preview", UI_EMBOSS, UI_HELV, sa->win);
2597 uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | UI_PNL_SCALE | cntrl);
2598 uiSetPanelHandler(VIEW3D_HANDLER_PREVIEW); // for close and esc
2600 ofsx= -150+(sa->winx/2)/v3d->blockscale;
2601 ofsy= -100+(sa->winy/2)/v3d->blockscale;
2602 if(uiNewPanel(sa, block, "Preview", "View3d", ofsx, ofsy, 300, 200)==0) return;
2604 uiBlockSetDrawExtraFunc(block, BIF_view3d_previewdraw);
2606 if(G.scene->recalc & SCE_PRV_CHANGED) {
2607 G.scene->recalc &= ~SCE_PRV_CHANGED;
2608 //printf("found recalc\n");
2609 BIF_view3d_previewrender_free(sa->spacedata.first);
2610 BIF_preview_changed(0);
2615 static void view3d_blockhandlers(ScrArea *sa)
2617 View3D *v3d= sa->spacedata.first;
2618 short a;
2620 /* warning; blocks need to be freed each time, handlers dont remove */
2621 uiFreeBlocksWin(&sa->uiblocks, sa->win);
2623 /*uv face-sel and wp mode when mixed with wire leave depth enabled causing
2624 models to draw over the UI */
2625 glDisable(GL_DEPTH_TEST);
2627 for(a=0; a<SPACE_MAXHANDLER; a+=2) {
2629 switch(v3d->blockhandler[a]) {
2631 case VIEW3D_HANDLER_PROPERTIES:
2632 view3d_panel_properties(v3d->blockhandler[a+1]);
2633 break;
2634 case VIEW3D_HANDLER_BACKGROUND:
2635 view3d_panel_background(v3d->blockhandler[a+1]);
2636 break;
2637 case VIEW3D_HANDLER_OBJECT:
2638 view3d_panel_object(v3d->blockhandler[a+1]);
2639 break;
2640 case VIEW3D_HANDLER_PREVIEW:
2641 view3d_panel_preview(sa, v3d->blockhandler[a+1]);
2642 break;
2644 /* clear action value for event */
2645 v3d->blockhandler[a+1]= 0;
2647 uiDrawBlocksPanels(sa, 0);
2651 /* ****************** View3d afterdraw *************** */
2653 typedef struct View3DAfter {
2654 struct View3DAfter *next, *prev;
2655 struct Base *base;
2656 int type;
2657 } View3DAfter;
2659 /* temp storage of Objects that need to be drawn as last */
2660 void add_view3d_after(View3D *v3d, Base *base, int type)
2662 View3DAfter *v3da= MEM_callocN(sizeof(View3DAfter), "View 3d after");
2664 BLI_addtail(&v3d->afterdraw, v3da);
2665 v3da->base= base;
2666 v3da->type= type;
2669 /* clears zbuffer and draws it over */
2670 static void view3d_draw_xray(View3D *v3d, int flag)
2672 View3DAfter *v3da, *next;
2673 int doit= 0;
2675 for(v3da= v3d->afterdraw.first; v3da; v3da= v3da->next)
2676 if(v3da->type==V3D_XRAY) doit= 1;
2678 if(doit) {
2679 if(v3d->zbuf) glClear(GL_DEPTH_BUFFER_BIT);
2680 v3d->xray= TRUE;
2682 for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
2683 next= v3da->next;
2684 if(v3da->type==V3D_XRAY) {
2685 draw_object(v3da->base, flag);
2686 BLI_remlink(&v3d->afterdraw, v3da);
2687 MEM_freeN(v3da);
2690 v3d->xray= FALSE;
2694 /* disables write in zbuffer and draws it over */
2695 static void view3d_draw_transp(View3D *v3d, int flag)
2697 View3DAfter *v3da, *next;
2699 glDepthMask(0);
2700 v3d->transp= TRUE;
2702 for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
2703 next= v3da->next;
2704 if(v3da->type==V3D_TRANSP) {
2705 draw_object(v3da->base, flag);
2706 BLI_remlink(&v3d->afterdraw, v3da);
2707 MEM_freeN(v3da);
2710 v3d->transp= FALSE;
2712 glDepthMask(1);
2716 /* *********************** */
2719 In most cases call draw_dupli_objects,
2720 draw_dupli_objects_color was added because when drawing set dupli's
2721 we need to force the color
2723 static void draw_dupli_objects_color(View3D *v3d, Base *base, int color)
2725 ListBase *lb;
2726 DupliObject *dob;
2727 Base tbase;
2728 BoundBox *bb= NULL;
2729 GLuint displist=0;
2730 short transflag, use_displist= -1; /* -1 is initialize */
2731 char dt, dtx;
2733 if (base->object->restrictflag & OB_RESTRICT_VIEW) return;
2735 /* test if we can do a displist */
2736 if(base->object->transflag & OB_DUPLIGROUP)
2737 use_displist= 0;
2739 tbase.flag= OB_FROMDUPLI|base->flag;
2740 lb= object_duplilist(G.scene, base->object);
2742 for(dob= lb->first; dob; dob= dob->next) {
2743 if(dob->no_draw);
2744 else {
2745 tbase.object= dob->ob;
2747 /* extra service: draw the duplicator in drawtype of parent */
2748 dt= tbase.object->dt; tbase.object->dt= base->object->dt;
2749 dtx= tbase.object->dtx; tbase.object->dtx= base->object->dtx;
2751 /* negative scale flag has to propagate */
2752 transflag= tbase.object->transflag;
2753 if(base->object->transflag & OB_NEG_SCALE)
2754 tbase.object->transflag ^= OB_NEG_SCALE;
2756 BIF_ThemeColorBlend(color, TH_BACK, 0.5);
2758 /* generate displist, test for new object */
2759 if(use_displist==1 && dob->prev && dob->prev->ob!=dob->ob) {
2760 use_displist= -1;
2761 glDeleteLists(displist, 1);
2763 /* generate displist */
2764 if(use_displist == -1) {
2766 /* lamp drawing messes with matrices, could be handled smarter... but this works */
2767 if(dob->ob->type==OB_LAMP)
2768 use_displist= 0;
2769 else {
2770 /* disable boundbox check for list creation */
2771 object_boundbox_flag(dob->ob, OB_BB_DISABLED, 1);
2772 /* need this for next part of code */
2773 bb= object_get_boundbox(dob->ob);
2775 Mat4One(dob->ob->obmat); /* obmat gets restored */
2777 displist= glGenLists(1);
2778 glNewList(displist, GL_COMPILE);
2779 draw_object(&tbase, DRAW_CONSTCOLOR);
2780 glEndList();
2782 use_displist= 1;
2783 object_boundbox_flag(dob->ob, OB_BB_DISABLED, 0);
2786 if(use_displist) {
2787 mymultmatrix(dob->mat);
2788 if(boundbox_clip(dob->mat, bb))
2789 glCallList(displist);
2790 myloadmatrix(G.vd->viewmat);
2792 else {
2793 Mat4CpyMat4(dob->ob->obmat, dob->mat);
2794 draw_object(&tbase, DRAW_CONSTCOLOR);
2797 tbase.object->dt= dt;
2798 tbase.object->dtx= dtx;
2799 tbase.object->transflag= transflag;
2803 /* Transp afterdraw disabled, afterdraw only stores base pointers, and duplis can be same obj */
2805 free_object_duplilist(lb); /* does restore */
2807 if(use_displist)
2808 glDeleteLists(displist, 1);
2811 static void draw_dupli_objects(View3D *v3d, Base *base)
2813 /* define the color here so draw_dupli_objects_color can be called
2814 * from the set loop */
2816 int color= (base->flag & SELECT)?TH_SELECT:TH_WIRE;
2817 /* debug */
2818 if(base->object->dup_group && base->object->dup_group->id.us<1)
2819 color= TH_REDALERT;
2821 draw_dupli_objects_color(v3d, base, color);
2824 void view3d_update_depths(View3D *v3d)
2826 /* Create storage for, and, if necessary, copy depth buffer */
2827 if(!v3d->depths) v3d->depths= MEM_callocN(sizeof(ViewDepths),"ViewDepths");
2828 if(v3d->depths) {
2829 ViewDepths *d= v3d->depths;
2830 if(d->w != v3d->area->winx ||
2831 d->h != v3d->area->winy ||
2832 !d->depths) {
2833 d->w= v3d->area->winx;
2834 d->h= v3d->area->winy;
2835 if(d->depths)
2836 MEM_freeN(d->depths);
2837 d->depths= MEM_mallocN(sizeof(float)*d->w*d->h,"View depths");
2838 d->damaged= 1;
2841 if(d->damaged) {
2842 glReadPixels(v3d->area->winrct.xmin,v3d->area->winrct.ymin,d->w,d->h,
2843 GL_DEPTH_COMPONENT,GL_FLOAT, d->depths);
2845 glGetDoublev(GL_DEPTH_RANGE,d->depth_range);
2847 d->damaged= 0;
2852 void drawview3dspace(ScrArea *sa, void *spacedata)
2854 View3D *v3d= spacedata;
2855 Base *base;
2856 Object *ob;
2857 Scene *sce;
2858 char retopo, sculpt;
2859 Object *obact = OBACT;
2861 /* update all objects, ipos, matrices, displists, etc. Flags set by depgraph or manual,
2862 no layer check here, gets correct flushed */
2863 /* sets first, we allow per definition current scene to have dependencies on sets */
2864 if(G.scene->set) {
2865 for(SETLOOPER(G.scene->set, base))
2866 object_handle_update(base->object); // bke_object.h
2868 for(base= G.scene->base.first; base; base= base->next)
2869 object_handle_update(base->object); // bke_object.h
2871 setwinmatrixview3d(sa->winx, sa->winy, NULL); /* 0= no pick rect */
2872 setviewmatrixview3d(); /* note: calls where_is_object for camera... */
2874 Mat4MulMat4(v3d->persmat, v3d->viewmat, sa->winmat);
2875 Mat4Invert(v3d->persinv, v3d->persmat);
2876 Mat4Invert(v3d->viewinv, v3d->viewmat);
2878 /* calculate pixelsize factor once, is used for lamps and obcenters */
2880 float len1, len2, vec[3];
2882 VECCOPY(vec, v3d->persinv[0]);
2883 len1= Normalize(vec);
2884 VECCOPY(vec, v3d->persinv[1]);
2885 len2= Normalize(vec);
2887 v3d->pixsize= 2.0f*(len1>len2?len1:len2);
2889 /* correct for window size */
2890 if(sa->winx > sa->winy) v3d->pixsize/= (float)sa->winx;
2891 else v3d->pixsize/= (float)sa->winy;
2894 if(v3d->drawtype > OB_WIRE) {
2895 if(G.f & G_SIMULATION)
2896 glClearColor(0.0, 0.0, 0.0, 0.0);
2897 else {
2898 float col[3];
2899 BIF_GetThemeColor3fv(TH_BACK, col);
2900 glClearColor(col[0], col[1], col[2], 0.0);
2902 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2904 glLoadIdentity();
2906 else {
2907 float col[3];
2908 BIF_GetThemeColor3fv(TH_BACK, col);
2909 glClearColor(col[0], col[1], col[2], 0.0);
2910 glClear(GL_COLOR_BUFFER_BIT);
2913 myloadmatrix(v3d->viewmat);
2914 persp(PERSP_STORE); // store correct view for persp(PERSP_VIEW) calls
2916 if(v3d->flag & V3D_CLIPPING)
2917 view3d_draw_clipping(v3d);
2919 /* set zbuffer after we draw clipping region */
2920 if(v3d->drawtype > OB_WIRE) {
2921 v3d->zbuf= TRUE;
2922 glEnable(GL_DEPTH_TEST);
2925 // needs to be done always, gridview is adjusted in drawgrid() now
2926 v3d->gridview= v3d->grid;
2928 if(v3d->view==0 || v3d->persp!=0) {
2929 drawfloor();
2930 if(v3d->persp==2) {
2931 if(G.scene->world) {
2932 if(G.scene->world->mode & WO_STARS) {
2933 RE_make_stars(NULL, star_stuff_init_func, star_stuff_vertex_func,
2934 star_stuff_term_func);
2937 if(v3d->flag & V3D_DISPBGPIC) draw_bgpic();
2940 else {
2941 drawgrid();
2943 if(v3d->flag & V3D_DISPBGPIC) {
2944 draw_bgpic();
2948 if(v3d->flag & V3D_CLIPPING)
2949 view3d_set_clipping(v3d);
2951 /* draw set first */
2952 if(G.scene->set) {
2953 for(SETLOOPER(G.scene->set, base)) {
2955 if(v3d->lay & base->lay) {
2957 BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
2958 draw_object(base, DRAW_CONSTCOLOR);
2960 if(base->object->transflag & OB_DUPLI) {
2961 draw_dupli_objects_color(v3d, base, TH_WIRE);
2966 /* Transp and X-ray afterdraw stuff */
2967 view3d_draw_xray(v3d, DRAW_CONSTCOLOR); // clears zbuffer if it is used!
2968 view3d_draw_transp(v3d, DRAW_CONSTCOLOR);
2971 /* then draw not selected and the duplis, but skip editmode object */
2972 for(base= G.scene->base.first; base; base= base->next) {
2973 if(v3d->lay & base->lay) {
2975 /* dupli drawing */
2976 if(base->object->transflag & OB_DUPLI) {
2977 draw_dupli_objects(v3d, base);
2979 if((base->flag & SELECT)==0) {
2980 if(base->object!=G.obedit) draw_object(base, 0);
2985 retopo= retopo_mesh_check() || retopo_curve_check();
2986 sculpt= (G.f & G_SCULPTMODE) && !G.obedit;
2987 if(retopo)
2988 view3d_update_depths(v3d);
2990 /* draw selected and editmode */
2991 for(base= G.scene->base.first; base; base= base->next) {
2992 if(v3d->lay & base->lay) {
2993 if (base->object==G.obedit || ( base->flag & SELECT) )
2994 draw_object(base, 0);
2998 if(!retopo && sculpt && !(obact && (obact->dtx & OB_DRAWXRAY)))
2999 view3d_update_depths(v3d);
3001 if(G.moving) {
3002 BIF_drawConstraint();
3003 if(G.obedit) BIF_drawPropCircle(); // only editmode has proportional edit
3004 BIF_drawSnap();
3007 if(G.scene->radio) RAD_drawall(v3d->drawtype>=OB_SOLID);
3009 /* Transp and X-ray afterdraw stuff */
3010 view3d_draw_xray(v3d, 0); // clears zbuffer if it is used!
3011 view3d_draw_transp(v3d, 0);
3013 if(!retopo && sculpt && (obact && (OBACT->dtx & OB_DRAWXRAY)))
3014 view3d_update_depths(v3d);
3016 if(v3d->flag & V3D_CLIPPING)
3017 view3d_clr_clipping();
3019 BIF_draw_manipulator(sa);
3021 if(v3d->zbuf) {
3022 v3d->zbuf= FALSE;
3023 glDisable(GL_DEPTH_TEST);
3026 persp(PERSP_WIN); // set ortho
3028 /* Draw Sculpt Mode brush */
3029 if(!G.obedit && (G.f & G_SCULPTMODE) && area_is_active_area(v3d->area) && sculpt_session()) {
3030 PropsetData *pd= sculpt_session()->propset;
3031 short r1=100, r2=100, r3=100;
3032 short mouse[2];
3033 if(pd) {
3034 if(pd->mode == PropsetSize) {
3035 r1= sculptmode_brush()->size;
3036 r2= pd->origsize;
3037 r3= r1;
3038 } else if(pd->mode == PropsetStrength) {
3039 r1= 200 - sculptmode_brush()->strength * 2;
3040 r2= 200;
3041 r3= 200;
3042 } else if(pd->mode == PropsetTexRot) {
3043 r1= r2= 200;
3044 r3= 200;
3047 /* Draw brush with texture */
3048 glEnable(GL_BLEND);
3049 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3051 glBindTexture(GL_TEXTURE_2D, pd->tex);
3053 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3054 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3056 glPushMatrix();
3057 glTranslatef(pd->origloc[0], pd->origloc[1], 0);
3058 glRotatef(tex_angle(), 0, 0, 1);
3060 glEnable(GL_TEXTURE_2D);
3061 glBegin(GL_QUADS);
3062 glColor4f(0,0,0,1);
3063 glTexCoord2f(0,0);
3064 glVertex2f(-r3, -r3);
3065 glTexCoord2f(1,0);
3066 glVertex2f(r3, -r3);
3067 glTexCoord2f(1,1);
3068 glVertex2f(r3, r3);
3069 glTexCoord2f(0,1);
3070 glVertex2f(-r3, r3);
3071 glEnd();
3072 glDisable(GL_TEXTURE_2D);
3074 glPopMatrix();
3076 if(r1 != r2)
3077 fdrawXORcirc(pd->origloc[0], pd->origloc[1], r1);
3078 fdrawXORcirc(pd->origloc[0], pd->origloc[1], r2);
3080 if(pd->mode == PropsetTexRot) {
3081 const float ang= pd->origtexrot * (M_PI/180.0f);
3082 getmouseco_areawin(mouse);
3083 sdrawXORline(pd->origloc[0], pd->origloc[1],
3084 pd->origloc[0]+200*cos(ang), pd->origloc[1]+200*sin(ang));
3085 sdrawXORline(pd->origloc[0], pd->origloc[1], mouse[0], mouse[1]);
3088 else if(sculpt_data()->draw_flag & SCULPTDRAW_BRUSH) {
3089 short csc[2], car[2];
3090 getmouseco_sc(csc);
3091 getmouseco_areawin(car);
3092 if(csc[0] > v3d->area->winrct.xmin &&
3093 csc[1] > v3d->area->winrct.ymin &&
3094 csc[0] < v3d->area->winrct.xmax &&
3095 csc[1] < v3d->area->winrct.ymax)
3096 fdrawXORcirc((float)car[0], (float)car[1], sculptmode_brush()->size);
3099 retopo_draw_paint_lines();
3101 if(v3d->persp>1) drawviewborder();
3102 if(v3d->flag2 & V3D_FLYMODE) drawviewborder_flymode();
3103 if(!(G.f & G_PLAYANIM)) drawcursor(v3d);
3104 if(U.uiflag & USER_SHOW_ROTVIEWICON)
3105 draw_view_axis();
3106 else
3107 draw_view_icon();
3108 if(U.uiflag & USER_SHOW_VIEWPORTNAME)
3109 draw_viewport_name(sa);
3111 ob= OBACT;
3112 if(ob && (U.uiflag & USER_DRAWVIEWINFO))
3113 draw_selected_name(ob);
3115 draw_area_emboss(sa);
3117 /* it is important to end a view in a transform compatible with buttons */
3119 bwin_scalematrix(sa->win, v3d->blockscale, v3d->blockscale, v3d->blockscale);
3120 view3d_blockhandlers(sa);
3122 sa->win_swap= WIN_BACK_OK;
3124 if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT)) {
3125 v3d->flag |= V3D_NEEDBACKBUFDRAW;
3126 addafterqueue(sa->win, BACKBUFDRAW, 1);
3128 // test for backbuf select
3129 if(G.obedit && v3d->drawtype>OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT)) {
3130 extern int afterqtest(short win, unsigned short evt); //editscreen.c
3132 v3d->flag |= V3D_NEEDBACKBUFDRAW;
3133 if(afterqtest(sa->win, BACKBUFDRAW)==0) {
3134 addafterqueue(sa->win, BACKBUFDRAW, 1);
3138 /* run any view3d draw handler script links */
3139 if (sa->scriptlink.totscript)
3140 BPY_do_spacehandlers(sa, 0, SPACEHANDLER_VIEW3D_DRAW);
3142 /* run scene redraw script links */
3143 if((G.f & G_DOSCRIPTLINKS) && G.scene->scriptlink.totscript &&
3144 !during_script()) {
3145 BPY_do_pyscript((ID *)G.scene, SCRIPT_REDRAW);
3151 void drawview3d_render(struct View3D *v3d, int winx, int winy, float winmat[][4])
3153 Base *base;
3154 Scene *sce;
3155 float v3dwinmat[4][4];
3157 setviewmatrixview3d();
3158 myloadmatrix(v3d->viewmat);
3160 /* when winmat is not NULL, it overrides the regular window matrix */
3161 glMatrixMode(GL_PROJECTION);
3162 if(winmat)
3163 myloadmatrix(winmat);
3164 else
3165 setwinmatrixview3d(winx, winy, NULL);
3166 mygetmatrix(v3dwinmat);
3167 glMatrixMode(GL_MODELVIEW);
3169 Mat4MulMat4(v3d->persmat, v3d->viewmat, v3dwinmat);
3170 Mat4Invert(v3d->persinv, v3d->persmat);
3171 Mat4Invert(v3d->viewinv, v3d->viewmat);
3173 free_all_realtime_images();
3174 reshadeall_displist();
3176 if(v3d->drawtype > OB_WIRE) {
3177 v3d->zbuf= TRUE;
3178 glEnable(GL_DEPTH_TEST);
3181 if(v3d->flag & V3D_CLIPPING)
3182 view3d_set_clipping(v3d);
3184 if (v3d->drawtype==OB_TEXTURE && G.scene->world) {
3185 glClearColor(G.scene->world->horr, G.scene->world->horg, G.scene->world->horb, 0.0);
3186 } else {
3187 float col[3];
3188 BIF_GetThemeColor3fv(TH_BACK, col);
3189 glClearColor(col[0], col[1], col[2], 0.0);
3191 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3193 /* abuse! to make sure it doesnt draw the helpstuff */
3194 G.f |= G_SIMULATION;
3196 /* first draw set */
3197 if(G.scene->set) {
3199 for(SETLOOPER(G.scene->set, base)) {
3200 if(v3d->lay & base->lay) {
3201 if ELEM3(base->object->type, OB_LAMP, OB_CAMERA, OB_LATTICE);
3202 else {
3203 where_is_object(base->object);
3205 BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
3206 draw_object(base, DRAW_CONSTCOLOR);
3208 if(base->object->transflag & OB_DUPLI) {
3209 draw_dupli_objects(v3d, base);
3215 /* Transp and X-ray afterdraw stuff */
3216 view3d_draw_xray(v3d, DRAW_CONSTCOLOR); // clears zbuffer if it is used!
3217 view3d_draw_transp(v3d, DRAW_CONSTCOLOR);
3220 /* first not selected and duplis */
3221 base= G.scene->base.first;
3222 while(base) {
3224 if(v3d->lay & base->lay) {
3225 if ELEM3(base->object->type, OB_LAMP, OB_CAMERA, OB_LATTICE);
3226 else {
3228 if(base->object->transflag & OB_DUPLI) {
3229 draw_dupli_objects(v3d, base);
3231 else if((base->flag & SELECT)==0) {
3232 draw_object(base, 0);
3237 base= base->next;
3240 /* draw selected */
3241 base= G.scene->base.first;
3242 while(base) {
3244 if ( ((base)->flag & SELECT) && ((base)->lay & v3d->lay) ) {
3245 if ELEM3(base->object->type, OB_LAMP, OB_CAMERA, OB_LATTICE);
3246 else draw_object(base, 0);
3249 base= base->next;
3252 if(G.scene->radio) RAD_drawall(v3d->drawtype>=OB_SOLID);
3254 /* Transp and X-ray afterdraw stuff */
3255 view3d_draw_xray(v3d, 0); // clears zbuffer if it is used!
3256 view3d_draw_transp(v3d, 0);
3258 if(v3d->flag & V3D_CLIPPING)
3259 view3d_clr_clipping();
3261 if(v3d->zbuf) {
3262 v3d->zbuf= FALSE;
3263 glDisable(GL_DEPTH_TEST);
3266 G.f &= ~G_SIMULATION;
3268 glFlush();
3270 glLoadIdentity();
3272 free_all_realtime_images();
3276 double tottime = 0.0;
3278 int update_time(void)
3280 static double ltime;
3281 double time;
3283 if ((audiostream_pos() != CFRA)
3284 && (G.scene->audio.flag & AUDIO_SYNC)) {
3285 return 0;
3288 time = PIL_check_seconds_timer();
3290 tottime += (time - ltime);
3291 ltime = time;
3292 return (tottime < 0.0);
3295 void inner_play_anim_loop(int init, int mode)
3297 ScrArea *sa;
3298 static ScrArea *oldsa;
3299 static double swaptime;
3300 static int curmode;
3302 /* init */
3303 if(init) {
3304 oldsa= curarea;
3305 swaptime= 1.0/FPS;
3306 tottime= 0.0;
3307 curmode= mode;
3309 return;
3312 set_timecursor(CFRA);
3314 update_for_newframe_nodraw(1); /* adds no events in UI */
3316 sa= G.curscreen->areabase.first;
3317 while(sa) {
3318 if(sa==oldsa) {
3319 scrarea_do_windraw(sa);
3321 else if(curmode & 1) { /* all view3d and seq spaces */
3322 if ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_SEQ) {
3323 scrarea_do_windraw(sa);
3326 else if(curmode & 4) { /* all seq spaces */
3327 if (sa->spacetype == SPACE_SEQ) {
3328 scrarea_do_windraw(sa);
3332 sa= sa->next;
3335 /* make sure that swaptime passed by */
3336 tottime -= swaptime;
3337 while (update_time()) PIL_sleep_ms(1);
3339 if(CFRA>=PEFRA) {
3340 if (tottime > 0.0) tottime = 0.0;
3341 CFRA= PSFRA;
3342 audiostream_stop();
3343 audiostream_start( CFRA );
3345 else {
3346 if (U.mixbufsize && (G.scene->audio.flag & AUDIO_SYNC)) CFRA = audiostream_pos();
3347 else CFRA++;
3351 /* play_anim: 'mode' defines where to play and if repeat is on (now bitfield):
3352 * - mode & 1 : All view3d and seq areas
3353 * - mode & 2 : No replay
3354 * - mode & 4 : All seq areas
3356 int play_anim(int mode)
3358 ScrArea *sa, *oldsa;
3359 int cfraont;
3360 unsigned short event=0;
3361 short val;
3363 /* patch for very very old scenes */
3364 if(SFRA==0) SFRA= 1;
3365 if(EFRA==0) EFRA= 250;
3367 if(PSFRA>PEFRA) return 0;
3369 update_time();
3371 /* waitcursor(1); */
3372 G.f |= G_PLAYANIM; /* in sequence.c and view.c this is handled */
3374 cfraont= CFRA;
3375 oldsa= curarea;
3377 audiostream_start( CFRA );
3379 if (curarea && curarea->spacetype == SPACE_SEQ) {
3380 SpaceSeq *sseq = curarea->spacedata.first;
3381 if (sseq->mainb == 0) mode |= 4;
3384 inner_play_anim_loop(1, mode); /* 1==init */
3386 /* forces all buffers to be OK for current frame (otherwise other windows get redrawn with CFRA+1) */
3387 curarea->win_swap= WIN_BACK_OK;
3388 screen_swapbuffers();
3390 while(TRUE) {
3392 while(qtest()) {
3394 /* we test events first because of MKEY event */
3396 event= extern_qread(&val);
3397 if(event==ESCKEY) break;
3398 else if(event==MIDDLEMOUSE) {
3399 if(U.flag & USER_VIEWMOVE) {
3400 if(G.qual & LR_SHIFTKEY) viewmove(0);
3401 else if(G.qual & LR_CTRLKEY) viewmove(2);
3402 else viewmove(1);
3404 else {
3405 if(G.qual & LR_SHIFTKEY) viewmove(1);
3406 else if(G.qual & LR_CTRLKEY) viewmove(2);
3407 else viewmove(0);
3410 else if(event==MKEY) {
3411 if(val) add_marker(CFRA-1);
3414 if(ELEM3(event, ESCKEY, SPACEKEY, RIGHTMOUSE)) break;
3416 inner_play_anim_loop(0, 0);
3417 screen_swapbuffers();
3419 if((mode & 2) && CFRA==PEFRA) break; /* no replay */
3422 if(event==SPACEKEY);
3423 else CFRA= cfraont;
3425 audiostream_stop();
3427 if(oldsa!=curarea) areawinset(oldsa->win);
3429 /* restore all areas */
3430 sa= G.curscreen->areabase.first;
3431 while(sa) {
3432 if( ((mode & 1) && sa->spacetype==SPACE_VIEW3D) || sa==curarea) addqueue(sa->win, REDRAW, 1);
3433 sa= sa->next;
3436 /* groups could have changed ipo */
3437 allspace(REMAKEIPO, 0);
3438 allqueue(REDRAWIPO, 0);
3439 allqueue(REDRAWNLA, 0);
3440 allqueue (REDRAWACTION, 0);
3442 /* restore for cfra */
3443 update_for_newframe_muted();
3445 waitcursor(0);
3446 G.f &= ~G_PLAYANIM;
3448 if (event==ESCKEY || event==SPACEKEY) return 1;
3449 else return 0;