fix for error in previous commit.
[blender.git] / source / blender / editors / space_view3d / drawobject.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, full recode and added functions
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/space_view3d/drawobject.c
27  *  \ingroup spview3d
28  */
29
30
31 #include <string.h>
32 #include <math.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "DNA_camera_types.h"
37 #include "DNA_curve_types.h"
38 #include "DNA_constraint_types.h" // for drawing constraint
39 #include "DNA_lamp_types.h"
40 #include "DNA_lattice_types.h"
41 #include "DNA_material_types.h"
42 #include "DNA_mesh_types.h"
43 #include "DNA_meshdata_types.h"
44 #include "DNA_meta_types.h"
45 #include "DNA_scene_types.h"
46 #include "DNA_smoke_types.h"
47 #include "DNA_speaker_types.h"
48 #include "DNA_world_types.h"
49 #include "DNA_armature_types.h"
50 #include "DNA_object_types.h"
51
52 #include "BLI_utildefines.h"
53 #include "BLI_blenlib.h"
54 #include "BLI_math.h"
55 #include "BLI_edgehash.h"
56 #include "BLI_rand.h"
57 #include "BLI_utildefines.h"
58
59 #include "BKE_anim.h"  //for the where_on_path function
60 #include "BKE_armature.h"
61 #include "BKE_camera.h"
62 #include "BKE_constraint.h" // for the get_constraint_target function
63 #include "BKE_curve.h"
64 #include "BKE_DerivedMesh.h"
65 #include "BKE_deform.h"
66 #include "BKE_displist.h"
67 #include "BKE_font.h"
68 #include "BKE_global.h"
69 #include "BKE_image.h"
70 #include "BKE_key.h"
71 #include "BKE_lattice.h"
72 #include "BKE_mesh.h"
73 #include "BKE_material.h"
74 #include "BKE_mball.h"
75 #include "BKE_modifier.h"
76 #include "BKE_object.h"
77 #include "BKE_paint.h"
78 #include "BKE_particle.h"
79 #include "BKE_pointcache.h"
80 #include "BKE_scene.h"
81 #include "BKE_unit.h"
82 #include "BKE_movieclip.h"
83 #include "BKE_tracking.h"
84
85 #include "BKE_tessmesh.h"
86
87 #include "smoke_API.h"
88
89 #include "IMB_imbuf.h"
90 #include "IMB_imbuf_types.h"
91
92 #include "BIF_gl.h"
93 #include "BIF_glutil.h"
94
95 #include "GPU_draw.h"
96 #include "GPU_extensions.h"
97
98 #include "ED_mesh.h"
99 #include "ED_particle.h"
100 #include "ED_screen.h"
101 #include "ED_sculpt.h"
102 #include "ED_types.h"
103 #include "ED_curve.h" /* for curve_editnurbs */
104
105 #include "UI_resources.h"
106
107 #include "WM_api.h"
108 #include "wm_subwindow.h"
109 #include "BLF_api.h"
110
111 #include "view3d_intern.h"  // own include
112
113 typedef enum eWireDrawMode {
114         OBDRAW_WIRE_OFF = 0,
115         OBDRAW_WIRE_ON = 1,
116         OBDRAW_WIRE_ON_DEPTH = 2
117 } eWireDrawMode;
118
119 /* user data structures for derived mesh callbacks */
120 typedef struct foreachScreenVert_userData {
121         void (*func)(void *userData, BMVert *eve, int x, int y, int index);
122         void *userData;
123         ViewContext vc;
124         eV3DClipTest clipVerts;
125 } foreachScreenVert_userData;
126
127 typedef struct foreachScreenEdge_userData {
128         void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index);
129         void *userData;
130         ViewContext vc;
131         rcti win_rect; /* copy of: vc.ar->winx/winy, use for faster tests, minx/y will always be 0 */
132         eV3DClipTest clipVerts;
133 } foreachScreenEdge_userData;
134
135 typedef struct foreachScreenFace_userData {
136         void (*func)(void *userData, BMFace *efa, int x, int y, int index);
137         void *userData;
138         ViewContext vc;
139 } foreachScreenFace_userData;
140
141 typedef struct drawDMVerts_userData {
142         BMEditMesh *em; /* BMESH BRANCH ONLY */
143
144         int sel;
145         BMVert *eve_act;
146
147         /* cached theme values */
148         unsigned char th_editmesh_active[4];
149         unsigned char th_vertex_select[4];
150         unsigned char th_vertex[4];
151         unsigned char th_skin_root[4];
152         float th_vertex_size;
153
154         /* for skin node drawing */
155         int has_vskin;
156         float imat[4][4];
157 } drawDMVerts_userData;
158
159 typedef struct drawDMEdgesSel_userData {
160         BMEditMesh *em; /* BMESH BRANCH ONLY */
161
162         unsigned char *baseCol, *selCol, *actCol;
163         BMEdge *eed_act;
164 } drawDMEdgesSel_userData;
165
166 typedef struct drawDMFacesSel_userData {
167         unsigned char *cols[3];
168
169         DerivedMesh *dm; /* BMESH BRANCH ONLY */
170         BMEditMesh *em;  /* BMESH BRANCH ONLY */
171
172         BMFace *efa_act;
173         int *orig_index;
174 } drawDMFacesSel_userData;
175
176 typedef struct drawDMNormal_userData {
177         BMEditMesh *em;
178         int uniform_scale;
179         float normalsize;
180         float tmat[3][3];
181         float imat[3][3];
182 } drawDMNormal_userData;
183
184 typedef struct bbsObmodeMeshVerts_userData {
185         void *offset;
186         MVert *mvert;
187 } bbsObmodeMeshVerts_userData;
188
189 static void draw_bounding_volume(Scene *scene, Object *ob, char type);
190
191 static void drawcube_size(float size);
192 static void drawcircle_size(float size);
193 static void draw_empty_sphere(float size);
194 static void draw_empty_cone(float size);
195
196 /* this condition has been made more complex since editmode can draw textures */
197 static int check_object_draw_texture(Scene *scene, View3D *v3d, int drawtype)
198 {
199         /* texture and material draw modes */
200         if (ELEM(v3d->drawtype, OB_TEXTURE, OB_MATERIAL) && drawtype > OB_SOLID)
201                 return TRUE;
202
203         /* textured solid */
204         if (v3d->drawtype == OB_SOLID && (v3d->flag2 & V3D_SOLID_TEX) && !BKE_scene_use_new_shading_nodes(scene))
205                 return TRUE;
206         
207         return FALSE;
208 }
209
210 static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
211 {
212         if ((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0)
213                 return 0;
214
215         if (G.f & G_BACKBUFSEL)
216                 return 0;
217
218         if ((vd->flag & V3D_ZBUF_SELECT) == 0)
219                 return 1;
220
221         /* if its drawing textures with zbuf sel, then don't draw dots */
222         if (dt == OB_TEXTURE && vd->drawtype == OB_TEXTURE)
223                 return 0;
224
225         if ((vd->drawtype >= OB_SOLID) && (vd->flag2 & V3D_SOLID_TEX))
226                 return 0;
227
228         return 1;
229 }
230
231 /* ************* only use while object drawing **************
232  * or after running ED_view3d_init_mats_rv3d
233  * */
234 static void view3d_project_short_clip(ARegion *ar, const float vec[3], short adr[2], int is_local)
235 {
236         RegionView3D *rv3d = ar->regiondata;
237         float fx, fy, vec4[4];
238         
239         adr[0] = IS_CLIPPED;
240         
241         /* clipplanes in eye space */
242         if (rv3d->rflag & RV3D_CLIPPING) {
243                 if (ED_view3d_clipping_test(rv3d, vec, is_local))
244                         return;
245         }
246         
247         copy_v3_v3(vec4, vec);
248         vec4[3] = 1.0;
249         
250         mul_m4_v4(rv3d->persmatob, vec4);
251         
252         /* clipplanes in window space */
253         if (vec4[3] > (float)BL_NEAR_CLIP) {    /* is the NEAR clipping cutoff for picking */
254                 fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]);
255                 
256                 if (fx > 0 && fx < ar->winx) {
257                         
258                         fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]);
259                         
260                         if (fy > 0.0f && fy < (float)ar->winy) {
261                                 adr[0] = (short)floorf(fx);
262                                 adr[1] = (short)floorf(fy);
263                         }
264                 }
265         }
266 }
267
268 /* BMESH NOTE: this function is unused in bmesh only */
269
270 /* only use while object drawing */
271 static void UNUSED_FUNCTION(view3d_project_short_noclip) (ARegion * ar, const float vec[3], short adr[2])
272 {
273         RegionView3D *rv3d = ar->regiondata;
274         float fx, fy, vec4[4];
275         
276         adr[0] = IS_CLIPPED;
277         
278         copy_v3_v3(vec4, vec);
279         vec4[3] = 1.0;
280         
281         mul_m4_v4(rv3d->persmatob, vec4);
282         
283         if (vec4[3] > (float)BL_NEAR_CLIP) {    /* is the NEAR clipping cutoff for picking */
284                 fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]);
285                 
286                 if (fx > -32700 && fx < 32700) {
287                         
288                         fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]);
289                         
290                         if (fy > -32700.0f && fy < 32700.0f) {
291                                 adr[0] = (short)floorf(fx);
292                                 adr[1] = (short)floorf(fy);
293                         }
294                 }
295         }
296 }
297
298 /* same as view3d_project_short_clip but use persmat instead of persmatob for projection */
299 static void view3d_project_short_clip_persmat(ARegion *ar, const float vec[3], short adr[2], int is_local)
300 {
301         RegionView3D *rv3d = ar->regiondata;
302         float fx, fy, vec4[4];
303
304         adr[0] = IS_CLIPPED;
305
306         /* clipplanes in eye space */
307         if (rv3d->rflag & RV3D_CLIPPING) {
308                 if (ED_view3d_clipping_test(rv3d, vec, is_local))
309                         return;
310         }
311
312         copy_v3_v3(vec4, vec);
313         vec4[3] = 1.0;
314
315         mul_m4_v4(rv3d->persmat, vec4);
316
317         /* clipplanes in window space */
318         if (vec4[3] > (float)BL_NEAR_CLIP) {    /* is the NEAR clipping cutoff for picking */
319                 fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]);
320
321                 if (fx > 0 && fx < ar->winx) {
322
323                         fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]);
324
325                         if (fy > 0.0f && fy < (float)ar->winy) {
326                                 adr[0] = (short)floorf(fx);
327                                 adr[1] = (short)floorf(fy);
328                         }
329                 }
330         }
331 }
332 /* ************************ */
333
334 /* check for glsl drawing */
335
336 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
337 {
338         if (!GPU_glsl_support())
339                 return 0;
340         if (G.f & G_PICKSEL)
341                 return 0;
342         if (!check_object_draw_texture(scene, v3d, dt))
343                 return 0;
344         if (ob == OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
345                 return 0;
346         if (BKE_scene_use_new_shading_nodes(scene))
347                 return 0;
348         
349         return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID);
350 }
351
352 static int check_alpha_pass(Base *base)
353 {
354         if (base->flag & OB_FROMDUPLI)
355                 return 0;
356
357         if (G.f & G_PICKSEL)
358                 return 0;
359         
360         return (base->object->dtx & OB_DRAWTRANSP);
361 }
362
363 /***/
364 static unsigned int colortab[24] =
365 {0x0,       0xFF88FF, 0xFFBBFF,
366  0x403000,  0xFFFF88, 0xFFFFBB,
367  0x104040,  0x66CCCC, 0x77CCCC,
368  0x104010,  0x55BB55, 0x66FF66,
369  0xFFFFFF};
370
371
372 static float cube[8][3] = {
373         {-1.0, -1.0, -1.0},
374         {-1.0, -1.0,  1.0},
375         {-1.0,  1.0,  1.0},
376         {-1.0,  1.0, -1.0},
377         { 1.0, -1.0, -1.0},
378         { 1.0, -1.0,  1.0},
379         { 1.0,  1.0,  1.0},
380         { 1.0,  1.0, -1.0},
381 };
382
383 /* ----------------- OpenGL Circle Drawing - Tables for Optimized Drawing Speed ------------------ */
384 /* 32 values of sin function (still same result!) */
385 #define CIRCLE_RESOL 32
386
387 static const float sinval[CIRCLE_RESOL] = {
388         0.00000000,
389         0.20129852,
390         0.39435585,
391         0.57126821,
392         0.72479278,
393         0.84864425,
394         0.93775213,
395         0.98846832,
396         0.99871650,
397         0.96807711,
398         0.89780453,
399         0.79077573,
400         0.65137248,
401         0.48530196,
402         0.29936312,
403         0.10116832,
404         -0.10116832,
405         -0.29936312,
406         -0.48530196,
407         -0.65137248,
408         -0.79077573,
409         -0.89780453,
410         -0.96807711,
411         -0.99871650,
412         -0.98846832,
413         -0.93775213,
414         -0.84864425,
415         -0.72479278,
416         -0.57126821,
417         -0.39435585,
418         -0.20129852,
419         0.00000000
420 };
421
422 /* 32 values of cos function (still same result!) */
423 static const float cosval[CIRCLE_RESOL] = {
424         1.00000000,
425         0.97952994,
426         0.91895781,
427         0.82076344,
428         0.68896691,
429         0.52896401,
430         0.34730525,
431         0.15142777,
432         -0.05064916,
433         -0.25065253,
434         -0.44039415,
435         -0.61210598,
436         -0.75875812,
437         -0.87434661,
438         -0.95413925,
439         -0.99486932,
440         -0.99486932,
441         -0.95413925,
442         -0.87434661,
443         -0.75875812,
444         -0.61210598,
445         -0.44039415,
446         -0.25065253,
447         -0.05064916,
448         0.15142777,
449         0.34730525,
450         0.52896401,
451         0.68896691,
452         0.82076344,
453         0.91895781,
454         0.97952994,
455         1.00000000
456 };
457
458 static void draw_xyz_wire(const float c[3], float size, int axis)
459 {
460         float v1[3] = {0.f, 0.f, 0.f}, v2[3] = {0.f, 0.f, 0.f};
461         float dim = size * 0.1f;
462         float dx[3], dy[3], dz[3];
463
464         dx[0] = dim; dx[1] = 0.f; dx[2] = 0.f;
465         dy[0] = 0.f; dy[1] = dim; dy[2] = 0.f;
466         dz[0] = 0.f; dz[1] = 0.f; dz[2] = dim;
467
468         switch (axis) {
469                 case 0:     /* x axis */
470                         glBegin(GL_LINES);
471                         
472                         /* bottom left to top right */
473                         sub_v3_v3v3(v1, c, dx);
474                         sub_v3_v3(v1, dy);
475                         add_v3_v3v3(v2, c, dx);
476                         add_v3_v3(v2, dy);
477                         
478                         glVertex3fv(v1);
479                         glVertex3fv(v2);
480                         
481                         /* top left to bottom right */
482                         mul_v3_fl(dy, 2.f);
483                         add_v3_v3(v1, dy);
484                         sub_v3_v3(v2, dy);
485                         
486                         glVertex3fv(v1);
487                         glVertex3fv(v2);
488                         
489                         glEnd();
490                         break;
491                 case 1:     /* y axis */
492                         glBegin(GL_LINES);
493                         
494                         /* bottom left to top right */
495                         mul_v3_fl(dx, 0.75f);
496                         sub_v3_v3v3(v1, c, dx);
497                         sub_v3_v3(v1, dy);
498                         add_v3_v3v3(v2, c, dx);
499                         add_v3_v3(v2, dy);
500                         
501                         glVertex3fv(v1);
502                         glVertex3fv(v2);
503                         
504                         /* top left to center */
505                         mul_v3_fl(dy, 2.f);
506                         add_v3_v3(v1, dy);
507                         copy_v3_v3(v2, c);
508                         
509                         glVertex3fv(v1);
510                         glVertex3fv(v2);
511                         
512                         glEnd();
513                         break;
514                 case 2:     /* z axis */
515                         glBegin(GL_LINE_STRIP);
516                         
517                         /* start at top left */
518                         sub_v3_v3v3(v1, c, dx);
519                         add_v3_v3v3(v1, c, dz);
520                         
521                         glVertex3fv(v1);
522                         
523                         mul_v3_fl(dx, 2.f);
524                         add_v3_v3(v1, dx);
525
526                         glVertex3fv(v1);
527                         
528                         mul_v3_fl(dz, 2.f);
529                         sub_v3_v3(v1, dx);
530                         sub_v3_v3(v1, dz);
531                         
532                         glVertex3fv(v1);
533                         
534                         add_v3_v3(v1, dx);
535                 
536                         glVertex3fv(v1);
537                         
538                         glEnd();
539                         break;
540         }
541         
542 }
543
544 void drawaxes(float size, char drawtype)
545 {
546         int axis;
547         float v1[3] = {0.0, 0.0, 0.0};
548         float v2[3] = {0.0, 0.0, 0.0};
549         float v3[3] = {0.0, 0.0, 0.0};
550         
551         switch (drawtype) {
552
553                 case OB_PLAINAXES:
554                         for (axis = 0; axis < 3; axis++) {
555                                 glBegin(GL_LINES);
556
557                                 v1[axis] = size;
558                                 v2[axis] = -size;
559                                 glVertex3fv(v1);
560                                 glVertex3fv(v2);
561
562                                 /* reset v1 & v2 to zero */
563                                 v1[axis] = v2[axis] = 0.0f;
564
565                                 glEnd();
566                         }
567                         break;
568                 case OB_SINGLE_ARROW:
569
570                         glBegin(GL_LINES);
571                         /* in positive z direction only */
572                         v1[2] = size;
573                         glVertex3fv(v1);
574                         glVertex3fv(v2);
575                         glEnd();
576
577                         /* square pyramid */
578                         glBegin(GL_TRIANGLES);
579
580                         v2[0] = size * 0.035f; v2[1] = size * 0.035f;
581                         v3[0] = size * -0.035f; v3[1] = size * 0.035f;
582                         v2[2] = v3[2] = size * 0.75f;
583
584                         for (axis = 0; axis < 4; axis++) {
585                                 if (axis % 2 == 1) {
586                                         v2[0] = -v2[0];
587                                         v3[1] = -v3[1];
588                                 }
589                                 else {
590                                         v2[1] = -v2[1];
591                                         v3[0] = -v3[0];
592                                 }
593
594                                 glVertex3fv(v1);
595                                 glVertex3fv(v2);
596                                 glVertex3fv(v3);
597
598                         }
599                         glEnd();
600
601                         break;
602                 case OB_CUBE:
603                         drawcube_size(size);
604                         break;
605
606                 case OB_CIRCLE:
607                         drawcircle_size(size);
608                         break;
609
610                 case OB_EMPTY_SPHERE:
611                         draw_empty_sphere(size);
612                         break;
613
614                 case OB_EMPTY_CONE:
615                         draw_empty_cone(size);
616                         break;
617
618                 case OB_ARROWS:
619                 default:
620                 {
621                         for (axis = 0; axis < 3; axis++) {
622                                 const int arrow_axis = (axis == 0) ? 1 : 0;
623
624                                 glBegin(GL_LINES);
625
626                                 v2[axis] = size;
627                                 glVertex3fv(v1);
628                                 glVertex3fv(v2);
629                                 
630                                 v1[axis] = size * 0.85f;
631                                 v1[arrow_axis] = -size * 0.08f;
632                                 glVertex3fv(v1);
633                                 glVertex3fv(v2);
634                                 
635                                 v1[arrow_axis] = size * 0.08f;
636                                 glVertex3fv(v1);
637                                 glVertex3fv(v2);
638
639                                 glEnd();
640                                 
641                                 v2[axis] += size * 0.125f;
642
643                                 draw_xyz_wire(v2, size, axis);
644
645
646                                 /* reset v1 & v2 to zero */
647                                 v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f;
648                         }
649                         break;
650                 }
651         }
652 }
653
654
655 /* Function to draw an Image on a empty Object */
656 static void draw_empty_image(Object *ob)
657 {
658         Image *ima = (Image *)ob->data;
659         ImBuf *ibuf = ima ? BKE_image_get_ibuf(ima, NULL) : NULL;
660
661         float scale, ofs_x, ofs_y, sca_x, sca_y;
662         int ima_x, ima_y;
663
664         if (ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) {
665                 IMB_rect_from_float(ibuf);
666         }
667
668         /* Get the buffer dimensions so we can fallback to fake ones */
669         if (ibuf && ibuf->rect) {
670                 ima_x = ibuf->x;
671                 ima_y = ibuf->y;
672         }
673         else {
674                 ima_x = 1;
675                 ima_y = 1;
676         }
677
678         /* Get the image aspect even if the buffer is invalid */
679         if (ima) {
680                 if (ima->aspx > ima->aspy) {
681                         sca_x = 1.0f;
682                         sca_y = ima->aspy / ima->aspx;
683                 }
684                 else if (ima->aspx < ima->aspy) {
685                         sca_x = ima->aspx / ima->aspy;
686                         sca_y = 1.0f;
687                 }
688                 else {
689                         sca_x = 1.0f;
690                         sca_y = 1.0f;
691                 }
692         }
693         else {
694                 sca_x = 1.0f;
695                 sca_y = 1.0f;
696         }
697
698         /* Calculate the scale center based on objects origin */
699         ofs_x = ob->ima_ofs[0] * ima_x;
700         ofs_y = ob->ima_ofs[1] * ima_y;
701
702         glMatrixMode(GL_MODELVIEW);
703         glPushMatrix();
704
705         /* Make sure we are drawing at the origin */
706         glTranslatef(0.0f,  0.0f,  0.0f);
707
708         /* Calculate Image scale */
709         scale = (ob->empty_drawsize / (float)MAX2(ima_x * sca_x, ima_y * sca_y));
710
711         /* Set the object scale */
712         glScalef(scale * sca_x, scale * sca_y, 1.0f);
713
714         if (ibuf && ibuf->rect) {
715                 /* Setup GL params */
716                 glEnable(GL_BLEND);
717                 glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA);
718
719                 /* Use the object color and alpha */
720                 glColor4fv(ob->col);
721
722                 /* Draw the Image on the screen */
723                 glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, ibuf->rect);
724                 glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
725
726                 glDisable(GL_BLEND);
727         }
728
729         UI_ThemeColor((ob->flag & SELECT) ? TH_SELECT : TH_WIRE);
730
731         /* Calculate the outline vertex positions */
732         glBegin(GL_LINE_LOOP);
733         glVertex2f(ofs_x, ofs_y);
734         glVertex2f(ofs_x + ima_x, ofs_y);
735         glVertex2f(ofs_x + ima_x, ofs_y + ima_y);
736         glVertex2f(ofs_x, ofs_y + ima_y);
737         glEnd();
738
739         /* Reset GL settings */
740         glMatrixMode(GL_MODELVIEW);
741         glPopMatrix();
742 }
743
744 static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, float tmat[][4])
745 {
746         float vx[3], vy[3];
747         float *viter = (float *)verts;
748         unsigned int a;
749
750         mul_v3_v3fl(vx, tmat[0], rad);
751         mul_v3_v3fl(vy, tmat[1], rad);
752
753         for (a = 0; a < CIRCLE_RESOL; a++, viter += 3) {
754                 viter[0] = cent[0] + sinval[a] * vx[0] + cosval[a] * vy[0];
755                 viter[1] = cent[1] + sinval[a] * vx[1] + cosval[a] * vy[1];
756                 viter[2] = cent[2] + sinval[a] * vx[2] + cosval[a] * vy[2];
757         }
758 }
759
760 void drawcircball(int mode, const float cent[3], float rad, float tmat[][4])
761 {
762         float verts[CIRCLE_RESOL][3];
763
764         circball_array_fill(verts, cent, rad, tmat);
765
766         glEnableClientState(GL_VERTEX_ARRAY);
767         glVertexPointer(3, GL_FLOAT, 0, verts);
768         glDrawArrays(mode, 0, CIRCLE_RESOL);
769         glDisableClientState(GL_VERTEX_ARRAY);
770 }
771
772 /* circle for object centers, special_color is for library or ob users */
773 static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, int special_color)
774 {
775         const float size = ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f;
776         float verts[CIRCLE_RESOL][3];
777
778         /* using gldepthfunc guarantees that it does write z values,
779          * but not checks for it, so centers remain visible independent order of drawing */
780         if (v3d->zbuf) glDepthFunc(GL_ALWAYS);
781         glEnable(GL_BLEND);
782         
783         if (special_color) {
784                 if (selstate == ACTIVE || selstate == SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
785
786                 else glColor4ub(0x55, 0xCC, 0xCC, 155);
787         }
788         else {
789                 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
790                 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
791                 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
792         }
793
794         circball_array_fill(verts, co, size, rv3d->viewinv);
795
796         /* enable vertex array */
797         glEnableClientState(GL_VERTEX_ARRAY);
798         glVertexPointer(3, GL_FLOAT, 0, verts);
799
800         /* 1. draw filled, blended polygon */
801         glDrawArrays(GL_POLYGON, 0, CIRCLE_RESOL);
802
803         /* 2. draw outline */
804         UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
805         glDrawArrays(GL_LINE_LOOP, 0, CIRCLE_RESOL);
806
807         /* finish up */
808         glDisableClientState(GL_VERTEX_ARRAY);
809
810         glDisable(GL_BLEND);
811
812         if (v3d->zbuf) glDepthFunc(GL_LEQUAL);
813 }
814
815 /* *********** text drawing for object/particles/armature ************* */
816 static ListBase CachedText[3];
817 static int CachedTextLevel = 0;
818
819 typedef struct ViewCachedString {
820         struct ViewCachedString *next, *prev;
821         float vec[3];
822         union {
823                 unsigned char ub[4];
824                 int pack;
825         } col;
826         short sco[2];
827         short xoffs;
828         short flag;
829         int str_len, pad;
830         /* str is allocated past the end */
831 } ViewCachedString;
832
833 void view3d_cached_text_draw_begin(void)
834 {
835         ListBase *strings = &CachedText[CachedTextLevel];
836         strings->first = strings->last = NULL;
837         CachedTextLevel++;
838 }
839
840 void view3d_cached_text_draw_add(const float co[3],
841                                  const char *str,
842                                  short xoffs, short flag,
843                                  const unsigned char col[4])
844 {
845         int alloc_len = strlen(str) + 1;
846         ListBase *strings = &CachedText[CachedTextLevel - 1];
847         /* TODO, replace with more efficient malloc, perhaps memarena per draw? */
848         ViewCachedString *vos = MEM_callocN(sizeof(ViewCachedString) + alloc_len, "ViewCachedString");
849
850         BLI_addtail(strings, vos);
851         copy_v3_v3(vos->vec, co);
852         vos->col.pack = *((int *)col);
853         vos->xoffs = xoffs;
854         vos->flag = flag;
855         vos->str_len = alloc_len - 1;
856
857         /* allocate past the end */
858         memcpy(++vos, str, alloc_len);
859 }
860
861 void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[][4])
862 {
863         RegionView3D *rv3d = ar->regiondata;
864         ListBase *strings = &CachedText[CachedTextLevel - 1];
865         ViewCachedString *vos;
866         int tot = 0;
867         
868         /* project first and test */
869         for (vos = strings->first; vos; vos = vos->next) {
870                 if (mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE))
871                         mul_m4_v3(mat, vos->vec);
872
873                 if (vos->flag & V3D_CACHE_TEXT_GLOBALSPACE)
874                         view3d_project_short_clip_persmat(ar, vos->vec, vos->sco, (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0);
875                 else
876                         view3d_project_short_clip(ar, vos->vec, vos->sco, (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0);
877
878                 if (vos->sco[0] != IS_CLIPPED)
879                         tot++;
880         }
881
882         if (tot) {
883                 int col_pack_prev = 0;
884
885 #if 0
886                 bglMats mats; /* ZBuffer depth vars */
887                 double ux, uy, uz;
888                 float depth;
889
890                 if (v3d->zbuf)
891                         bgl_get_mats(&mats);
892 #endif
893                 if (rv3d->rflag & RV3D_CLIPPING) {
894                         ED_view3d_clipping_disable();
895                 }
896
897                 glMatrixMode(GL_PROJECTION);
898                 glPushMatrix();
899                 glMatrixMode(GL_MODELVIEW);
900                 glPushMatrix();
901                 ED_region_pixelspace(ar);
902                 
903                 if (depth_write) {
904                         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
905                 }
906                 else {
907                         glDepthMask(0);
908                 }
909                 
910                 for (vos = strings->first; vos; vos = vos->next) {
911                         /* too slow, reading opengl info while drawing is very bad,
912                          * better to see if we can use the zbuffer while in pixel space - campbell */
913 #if 0
914                         if (v3d->zbuf && (vos->flag & V3D_CACHE_TEXT_ZBUF)) {
915                                 gluProject(vos->vec[0], vos->vec[1], vos->vec[2], mats.modelview, mats.projection, (GLint *)mats.viewport, &ux, &uy, &uz);
916                                 glReadPixels(ar->winrct.xmin + vos->mval[0] + vos->xoffs, ar->winrct.ymin + vos->mval[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
917
918                                 if (uz > depth)
919                                         continue;
920                         }
921 #endif
922                         if (vos->sco[0] != IS_CLIPPED) {
923                                 const char *str = (char *)(vos + 1);
924
925                                 if (col_pack_prev != vos->col.pack) {
926                                         glColor3ubv(vos->col.ub);
927                                         col_pack_prev = vos->col.pack;
928                                 }
929
930                                 ((vos->flag & V3D_CACHE_TEXT_ASCII) ?
931                                  BLF_draw_default_ascii :
932                                  BLF_draw_default
933                                 )( (float)vos->sco[0] + vos->xoffs,
934                                    (float)vos->sco[1],
935                                    (depth_write) ? 0.0f : 2.0f,
936                                    str,
937                                    vos->str_len);
938                         }
939                 }
940                 
941                 if (depth_write) {
942                         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
943                 }
944                 else glDepthMask(1);
945                 
946                 glMatrixMode(GL_PROJECTION);
947                 glPopMatrix();
948                 glMatrixMode(GL_MODELVIEW);
949                 glPopMatrix();
950
951                 if (rv3d->rflag & RV3D_CLIPPING) {
952                         ED_view3d_clipping_enable();
953                 }
954         }
955         
956         if (strings->first)
957                 BLI_freelistN(strings);
958         
959         CachedTextLevel--;
960 }
961
962 /* ******************** primitive drawing ******************* */
963
964 static void drawcube(void)
965 {
966
967         glBegin(GL_LINE_STRIP);
968         glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
969         glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[6]);
970         glVertex3fv(cube[7]); glVertex3fv(cube[4]);
971         glEnd();
972
973         glBegin(GL_LINE_STRIP);
974         glVertex3fv(cube[1]); glVertex3fv(cube[5]);
975         glEnd();
976
977         glBegin(GL_LINE_STRIP);
978         glVertex3fv(cube[2]); glVertex3fv(cube[6]);
979         glEnd();
980
981         glBegin(GL_LINE_STRIP);
982         glVertex3fv(cube[3]); glVertex3fv(cube[7]);
983         glEnd();
984 }
985
986 /* draws a cube on given the scaling of the cube, assuming that 
987  * all required matrices have been set (used for drawing empties)
988  */
989 static void drawcube_size(float size)
990 {
991         glBegin(GL_LINE_STRIP);
992         glVertex3f(-size, -size, -size); glVertex3f(-size, -size, size);
993         glVertex3f(-size, size, size); glVertex3f(-size, size, -size);
994
995         glVertex3f(-size, -size, -size); glVertex3f(size, -size, -size);
996         glVertex3f(size, -size, size); glVertex3f(size, size, size);
997
998         glVertex3f(size, size, -size); glVertex3f(size, -size, -size);
999         glEnd();
1000
1001         glBegin(GL_LINE_STRIP);
1002         glVertex3f(-size, -size, size); glVertex3f(size, -size, size);
1003         glEnd();
1004
1005         glBegin(GL_LINE_STRIP);
1006         glVertex3f(-size, size, size); glVertex3f(size, size, size);
1007         glEnd();
1008
1009         glBegin(GL_LINE_STRIP);
1010         glVertex3f(-size, size, -size); glVertex3f(size, size, -size);
1011         glEnd();
1012 }
1013
1014 /* this is an unused (old) cube-drawing function based on a given size */
1015 #if 0
1016 static void drawcube_size(const float size[3])
1017 {
1018
1019         glPushMatrix();
1020         glScalef(size[0],  size[1],  size[2]);
1021         
1022
1023         glBegin(GL_LINE_STRIP);
1024         glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
1025         glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[6]);
1026         glVertex3fv(cube[7]); glVertex3fv(cube[4]);
1027         glEnd();
1028
1029         glBegin(GL_LINE_STRIP);
1030         glVertex3fv(cube[1]); glVertex3fv(cube[5]);
1031         glEnd();
1032
1033         glBegin(GL_LINE_STRIP);
1034         glVertex3fv(cube[2]); glVertex3fv(cube[6]);
1035         glEnd();
1036
1037         glBegin(GL_LINE_STRIP);
1038         glVertex3fv(cube[3]); glVertex3fv(cube[7]);
1039         glEnd();
1040         
1041         glPopMatrix();
1042 }
1043 #endif
1044
1045 static void drawshadbuflimits(Lamp *la, float mat[][4])
1046 {
1047         float sta[3], end[3], lavec[3];
1048
1049         negate_v3_v3(lavec, mat[2]);
1050         normalize_v3(lavec);
1051
1052         madd_v3_v3v3fl(sta, mat[3], lavec, la->clipsta);
1053         madd_v3_v3v3fl(end, mat[3], lavec, la->clipend);
1054
1055         glBegin(GL_LINE_STRIP);
1056         glVertex3fv(sta);
1057         glVertex3fv(end);
1058         glEnd();
1059
1060         glPointSize(3.0);
1061         bglBegin(GL_POINTS);
1062         bglVertex3fv(sta);
1063         bglVertex3fv(end);
1064         bglEnd();
1065         glPointSize(1.0);
1066 }
1067
1068
1069
1070 static void spotvolume(float lvec[3], float vvec[3], const float inp)
1071 {
1072         /* camera is at 0,0,0 */
1073         float temp[3], plane[3], mat1[3][3], mat2[3][3], mat3[3][3], mat4[3][3], q[4], co, si, angle;
1074
1075         normalize_v3(lvec);
1076         normalize_v3(vvec);             /* is this the correct vector ? */
1077
1078         cross_v3_v3v3(temp, vvec, lvec);      /* equation for a plane through vvec en lvec */
1079         cross_v3_v3v3(plane, lvec, temp);     /* a plane perpendicular to this, parrallel with lvec */
1080
1081         /* vectors are exactly aligned, use the X axis, this is arbitrary */
1082         if (normalize_v3(plane) == 0.0f)
1083                 plane[1] = 1.0f;
1084
1085         /* now we've got two equations: one of a cone and one of a plane, but we have
1086          * three unknowns. We remove one unknown by rotating the plane to z=0 (the plane normal) */
1087
1088         /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
1089         /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
1090
1091         /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
1092         
1093         q[1] =  plane[1];
1094         q[2] = -plane[0];
1095         q[3] =  0;
1096         normalize_v3(&q[1]);
1097
1098         angle = saacos(plane[2]) / 2.0f;
1099         co = cosf(angle);
1100         si = sqrtf(1 - co * co);
1101
1102         q[0] =  co;
1103         q[1] *= si;
1104         q[2] *= si;
1105         q[3] =  0;
1106
1107         quat_to_mat3(mat1, q);
1108
1109         /* rotate lamp vector now over acos(inp) degrees */
1110         copy_v3_v3(vvec, lvec);
1111
1112         unit_m3(mat2);
1113         co = inp;
1114         si = sqrtf(1.0f - inp * inp);
1115
1116         mat2[0][0] =  co;
1117         mat2[1][0] = -si;
1118         mat2[0][1] =  si;
1119         mat2[1][1] =  co;
1120         mul_m3_m3m3(mat3, mat2, mat1);
1121
1122         mat2[1][0] =  si;
1123         mat2[0][1] = -si;
1124         mul_m3_m3m3(mat4, mat2, mat1);
1125         transpose_m3(mat1);
1126
1127         mul_m3_m3m3(mat2, mat1, mat3);
1128         mul_m3_v3(mat2, lvec);
1129         mul_m3_m3m3(mat2, mat1, mat4);
1130         mul_m3_v3(mat2, vvec);
1131
1132         return;
1133 }
1134
1135 static void draw_spot_cone(Lamp *la, float x, float z)
1136 {
1137         z = fabs(z);
1138
1139         glBegin(GL_TRIANGLE_FAN);
1140         glVertex3f(0.0f, 0.0f, -x);
1141
1142         if (la->mode & LA_SQUARE) {
1143                 glVertex3f(z, z, 0);
1144                 glVertex3f(-z, z, 0);
1145                 glVertex3f(-z, -z, 0);
1146                 glVertex3f(z, -z, 0);
1147                 glVertex3f(z, z, 0);
1148         }
1149         else {
1150                 float angle;
1151                 int a;
1152
1153                 for (a = 0; a < 33; a++) {
1154                         angle = a * M_PI * 2 / (33 - 1);
1155                         glVertex3f(z * cosf(angle), z * sinf(angle), 0);
1156                 }
1157         }
1158
1159         glEnd();
1160 }
1161
1162 static void draw_transp_spot_volume(Lamp *la, float x, float z)
1163 {
1164         glEnable(GL_CULL_FACE);
1165         glEnable(GL_BLEND);
1166         glDepthMask(0);
1167
1168         /* draw backside darkening */
1169         glCullFace(GL_FRONT);
1170
1171         glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
1172         glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
1173
1174         draw_spot_cone(la, x, z);
1175
1176         /* draw front side lighting */
1177         glCullFace(GL_BACK);
1178
1179         glBlendFunc(GL_ONE, GL_ONE);
1180         glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
1181
1182         draw_spot_cone(la, x, z);
1183
1184         /* restore state */
1185         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1186         glDisable(GL_BLEND);
1187         glDepthMask(1);
1188         glDisable(GL_CULL_FACE);
1189         glCullFace(GL_BACK);
1190 }
1191
1192 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
1193                      int dt, int flag, const unsigned char ob_wire_col[4])
1194 {
1195         Object *ob = base->object;
1196         const float pixsize = ED_view3d_pixel_size(rv3d, ob->obmat[3]);
1197         Lamp *la = ob->data;
1198         float vec[3], lvec[3], vvec[3], circrad, x, y, z;
1199         float lampsize;
1200         float imat[4][4];
1201
1202         unsigned char curcol[4];
1203         unsigned char col[4];
1204         /* cone can't be drawn for duplicated lamps, because duplilist would be freed to */
1205         /* the moment of view3d_draw_transp() call */
1206         const short is_view = (rv3d->persp == RV3D_CAMOB && v3d->camera == base->object);
1207         const short drawcone = ((dt > OB_WIRE) &&
1208                                 !(G.f & G_PICKSEL) &&
1209                                 (la->type == LA_SPOT) &&
1210                                 (la->mode & LA_SHOW_CONE) &&
1211                                 !(base->flag & OB_FROMDUPLI) &&
1212                                 !is_view);
1213
1214         if (drawcone && !v3d->transp) {
1215                 /* in this case we need to draw delayed */
1216                 add_view3d_after(&v3d->afterdraw_transp, base, flag);
1217                 return;
1218         }
1219         
1220         /* we first draw only the screen aligned & fixed scale stuff */
1221         glPushMatrix();
1222         glLoadMatrixf(rv3d->viewmat);
1223
1224         /* lets calculate the scale: */
1225         lampsize = pixsize * ((float)U.obcenter_dia * 0.5f);
1226
1227         /* and view aligned matrix: */
1228         copy_m4_m4(imat, rv3d->viewinv);
1229         normalize_v3(imat[0]);
1230         normalize_v3(imat[1]);
1231
1232         /* lamp center */
1233         copy_v3_v3(vec, ob->obmat[3]);
1234
1235         if ((flag & DRAW_CONSTCOLOR) == 0) {
1236                 /* for AA effects */
1237                 curcol[0] = ob_wire_col[0];
1238                 curcol[1] = ob_wire_col[1];
1239                 curcol[2] = ob_wire_col[2];
1240                 curcol[3] = 154;
1241                 glColor4ubv(curcol);
1242         }
1243
1244         if (lampsize > 0.0f) {
1245
1246                 if ((flag & DRAW_CONSTCOLOR) == 0) {
1247                         if (ob->id.us > 1) {
1248                                 if (ob == OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
1249                                 else glColor4ub(0x77, 0xCC, 0xCC, 155);
1250                         }
1251                 }
1252                 
1253                 /* Inner Circle */
1254                 glEnable(GL_BLEND);
1255                 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
1256                 glDisable(GL_BLEND);
1257                 drawcircball(GL_POLYGON, vec, lampsize, imat);
1258                 
1259                 /* restore */
1260                 if ((flag & DRAW_CONSTCOLOR) == 0) {
1261                         if (ob->id.us > 1)
1262                                 glColor4ubv(curcol);
1263                 }
1264
1265                 /* Outer circle */
1266                 circrad = 3.0f * lampsize;
1267                 setlinestyle(3);
1268
1269                 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
1270
1271                 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
1272                 if (la->type != LA_HEMI) {
1273                         if ((la->mode & LA_SHAD_RAY) || ((la->mode & LA_SHAD_BUF) && (la->type == LA_SPOT))) {
1274                                 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f * pixsize, imat);
1275                         }
1276                 }
1277         }
1278         else {
1279                 setlinestyle(3);
1280                 circrad = 0.0f;
1281         }
1282         
1283         /* draw the pretty sun rays */
1284         if (la->type == LA_SUN) {
1285                 float v1[3], v2[3], mat[3][3];
1286                 short axis;
1287                 
1288                 /* setup a 45 degree rotation matrix */
1289                 vec_rot_to_mat3(mat, imat[2], (float)M_PI / 4.0f);
1290                 
1291                 /* vectors */
1292                 mul_v3_v3fl(v1, imat[0], circrad * 1.2f);
1293                 mul_v3_v3fl(v2, imat[0], circrad * 2.5f);
1294                 
1295                 /* center */
1296                 glTranslatef(vec[0], vec[1], vec[2]);
1297                 
1298                 setlinestyle(3);
1299                 
1300                 glBegin(GL_LINES);
1301                 for (axis = 0; axis < 8; axis++) {
1302                         glVertex3fv(v1);
1303                         glVertex3fv(v2);
1304                         mul_m3_v3(mat, v1);
1305                         mul_m3_v3(mat, v2);
1306                 }
1307                 glEnd();
1308                 
1309                 glTranslatef(-vec[0], -vec[1], -vec[2]);
1310
1311         }
1312         
1313         if (la->type == LA_LOCAL) {
1314                 if (la->mode & LA_SPHERE) {
1315                         drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
1316                 }
1317         }
1318         
1319         glPopMatrix();  /* back in object space */
1320         zero_v3(vec);
1321         
1322         if (is_view) {
1323                 /* skip drawing extra info */
1324         }
1325         else if ((la->type == LA_SPOT) || (la->type == LA_YF_PHOTON)) {
1326                 lvec[0] = lvec[1] = 0.0;
1327                 lvec[2] = 1.0;
1328                 x = rv3d->persmat[0][2];
1329                 y = rv3d->persmat[1][2];
1330                 z = rv3d->persmat[2][2];
1331                 vvec[0] = x * ob->obmat[0][0] + y * ob->obmat[0][1] + z * ob->obmat[0][2];
1332                 vvec[1] = x * ob->obmat[1][0] + y * ob->obmat[1][1] + z * ob->obmat[1][2];
1333                 vvec[2] = x * ob->obmat[2][0] + y * ob->obmat[2][1] + z * ob->obmat[2][2];
1334
1335                 y = cosf(la->spotsize * (float)(M_PI / 360.0));
1336                 spotvolume(lvec, vvec, y);
1337                 x = -la->dist;
1338                 mul_v3_fl(lvec, x);
1339                 mul_v3_fl(vvec, x);
1340
1341                 /* draw the angled sides of the cone */
1342                 glBegin(GL_LINE_STRIP);
1343                 glVertex3fv(vvec);
1344                 glVertex3fv(vec);
1345                 glVertex3fv(lvec);
1346                 glEnd();
1347                 
1348                 z = x * sqrtf(1.0f - y * y);
1349                 x *= y;
1350
1351                 /* draw the circle/square at the end of the cone */
1352                 glTranslatef(0.0, 0.0,  x);
1353                 if (la->mode & LA_SQUARE) {
1354                         float tvec[3];
1355                         float z_abs = fabs(z);
1356
1357                         tvec[0] = tvec[1] = z_abs;
1358                         tvec[2] = 0.0;
1359
1360                         glBegin(GL_LINE_LOOP);
1361                         glVertex3fv(tvec);
1362                         tvec[1] = -z_abs; /* neg */
1363                         glVertex3fv(tvec);
1364                         tvec[0] = -z_abs; /* neg */
1365                         glVertex3fv(tvec);
1366                         tvec[1] = z_abs; /* pos */
1367                         glVertex3fv(tvec);
1368                         glEnd();
1369                 }
1370                 else circ(0.0, 0.0, fabsf(z));
1371                 
1372                 /* draw the circle/square representing spotbl */
1373                 if (la->type == LA_SPOT) {
1374                         float spotblcirc = fabs(z) * (1 - pow(la->spotblend, 2));
1375                         /* hide line if it is zero size or overlaps with outer border,
1376                          * previously it adjusted to always to show it but that seems
1377                          * confusing because it doesn't show the actual blend size */
1378                         if (spotblcirc != 0 && spotblcirc != fabsf(z))
1379                                 circ(0.0, 0.0, spotblcirc);
1380                 }
1381
1382                 if (drawcone)
1383                         draw_transp_spot_volume(la, x, z);
1384
1385                 /* draw clip start, useful for wide cones where its not obvious where the start is */
1386                 glTranslatef(0.0, 0.0, -x);  /* reverse translation above */
1387                 if (la->type == LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
1388                         float lvec_clip[3];
1389                         float vvec_clip[3];
1390                         float clipsta_fac = la->clipsta / -x;
1391
1392                         interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac);
1393                         interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac);
1394
1395                         glBegin(GL_LINE_STRIP);
1396                         glVertex3fv(lvec_clip);
1397                         glVertex3fv(vvec_clip);
1398                         glEnd();
1399                 }
1400         }
1401         else if (ELEM(la->type, LA_HEMI, LA_SUN)) {
1402                 
1403                 /* draw the line from the circle along the dist */
1404                 glBegin(GL_LINE_STRIP);
1405                 vec[2] = -circrad;
1406                 glVertex3fv(vec);
1407                 vec[2] = -la->dist;
1408                 glVertex3fv(vec);
1409                 glEnd();
1410                 
1411                 if (la->type == LA_HEMI) {
1412                         /* draw the hemisphere curves */
1413                         short axis, steps, dir;
1414                         float outdist, zdist, mul;
1415                         zero_v3(vec);
1416                         outdist = 0.14; mul = 1.4; dir = 1;
1417                         
1418                         setlinestyle(4);
1419                         /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
1420                         for (axis = 0; axis < 4; axis++) {
1421                                 float v[3] = {0.0, 0.0, 0.0};
1422                                 zdist = 0.02;
1423                                 
1424                                 glBegin(GL_LINE_STRIP);
1425                                 
1426                                 for (steps = 0; steps < 6; steps++) {
1427                                         if (axis == 0 || axis == 1) {       /* x axis up, x axis down */
1428                                                 /* make the arcs start at the edge of the energy circle */
1429                                                 if (steps == 0) v[0] = dir * circrad;
1430                                                 else v[0] = v[0] + dir * (steps * outdist);
1431                                         }
1432                                         else if (axis == 2 || axis == 3) {      /* y axis up, y axis down */
1433                                                 /* make the arcs start at the edge of the energy circle */
1434                                                 v[1] = (steps == 0) ? (dir * circrad) : (v[1] + dir * (steps * outdist));
1435                                         }
1436
1437                                         v[2] = v[2] - steps * zdist;
1438                                         
1439                                         glVertex3fv(v);
1440                                         
1441                                         zdist = zdist * mul;
1442                                 }
1443                                 
1444                                 glEnd();
1445                                 /* flip the direction */
1446                                 dir = -dir;
1447                         }
1448                 }
1449         }
1450         else if (la->type == LA_AREA) {
1451                 setlinestyle(3);
1452                 if (la->area_shape == LA_AREA_SQUARE)
1453                         fdrawbox(-la->area_size * 0.5f, -la->area_size * 0.5f, la->area_size * 0.5f, la->area_size * 0.5f);
1454                 else if (la->area_shape == LA_AREA_RECT)
1455                         fdrawbox(-la->area_size * 0.5f, -la->area_sizey * 0.5f, la->area_size * 0.5f, la->area_sizey * 0.5f);
1456
1457                 glBegin(GL_LINE_STRIP);
1458                 glVertex3f(0.0, 0.0, -circrad);
1459                 glVertex3f(0.0, 0.0, -la->dist);
1460                 glEnd();
1461         }
1462         
1463         /* and back to viewspace */
1464         glLoadMatrixf(rv3d->viewmat);
1465         copy_v3_v3(vec, ob->obmat[3]);
1466
1467         setlinestyle(0);
1468         
1469         if ((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == FALSE)) {
1470                 drawshadbuflimits(la, ob->obmat);
1471         }
1472         
1473         UI_GetThemeColor4ubv(TH_LAMP, col);
1474         glColor4ubv(col);
1475
1476         glEnable(GL_BLEND);
1477         
1478         if (vec[2] > 0) vec[2] -= circrad;
1479         else vec[2] += circrad;
1480         
1481         glBegin(GL_LINE_STRIP);
1482         glVertex3fv(vec);
1483         vec[2] = 0;
1484         glVertex3fv(vec);
1485         glEnd();
1486         
1487         glPointSize(2.0);
1488         glBegin(GL_POINTS);
1489         glVertex3fv(vec);
1490         glEnd();
1491         glPointSize(1.0);
1492         
1493         glDisable(GL_BLEND);
1494         
1495         if ((flag & DRAW_CONSTCOLOR) == 0) {
1496                 /* restore for drawing extra stuff */
1497                 glColor3ubv(ob_wire_col);
1498         }
1499 }
1500
1501 static void draw_limit_line(float sta, float end, unsigned int col)
1502 {
1503         glBegin(GL_LINES);
1504         glVertex3f(0.0, 0.0, -sta);
1505         glVertex3f(0.0, 0.0, -end);
1506         glEnd();
1507
1508         glPointSize(3.0);
1509         glBegin(GL_POINTS);
1510         cpack(col);
1511         glVertex3f(0.0, 0.0, -sta);
1512         glVertex3f(0.0, 0.0, -end);
1513         glEnd();
1514         glPointSize(1.0);
1515 }               
1516
1517
1518 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1519 /* qdn: now also enabled for Blender to set focus point for defocus composite node */
1520 static void draw_focus_cross(float dist, float size)
1521 {
1522         glBegin(GL_LINES);
1523         glVertex3f(-size, 0.f, -dist);
1524         glVertex3f(size, 0.f, -dist);
1525         glVertex3f(0.f, -size, -dist);
1526         glVertex3f(0.f, size, -dist);
1527         glEnd();
1528 }
1529
1530 #ifdef VIEW3D_CAMERA_BORDER_HACK
1531 unsigned char view3d_camera_border_hack_col[3];
1532 short view3d_camera_border_hack_test = FALSE;
1533 #endif
1534
1535 /* ****************** draw clip data *************** */
1536
1537 static void draw_bundle_sphere(void)
1538 {
1539         static GLuint displist = 0;
1540
1541         if (displist == 0) {
1542                 GLUquadricObj *qobj;
1543
1544                 displist = glGenLists(1);
1545                 glNewList(displist, GL_COMPILE);
1546
1547                 qobj = gluNewQuadric();
1548                 gluQuadricDrawStyle(qobj, GLU_FILL);
1549                 glShadeModel(GL_SMOOTH);
1550                 gluSphere(qobj, 0.05, 8, 8);
1551                 glShadeModel(GL_FLAT);
1552                 gluDeleteQuadric(qobj);
1553
1554                 glEndList();
1555         }
1556
1557         glCallList(displist);
1558 }
1559
1560 static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D *v3d,
1561                                                 MovieClip *clip, MovieTrackingObject *tracking_object, int flag,
1562                                                 int *global_track_index, int draw_selected)
1563 {
1564         MovieTracking *tracking = &clip->tracking;
1565         MovieTrackingTrack *track;
1566         float mat[4][4], imat[4][4];
1567         unsigned char col[4], scol[4];
1568         int tracknr = *global_track_index;
1569         ListBase *tracksbase = BKE_tracking_object_tracks(tracking, tracking_object);
1570
1571         UI_GetThemeColor4ubv(TH_TEXT, col);
1572         UI_GetThemeColor4ubv(TH_SELECT, scol);
1573
1574         BKE_get_tracking_mat(scene, base->object, mat);
1575
1576         glPushMatrix();
1577
1578         if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
1579                 /* current ogl matrix is translated in camera space, bundles should
1580                  * be rendered in world space, so camera matrix should be "removed"
1581                  * from current ogl matrix */
1582                 invert_m4_m4(imat, base->object->obmat);
1583
1584                 glMultMatrixf(imat);
1585                 glMultMatrixf(mat);
1586         }
1587         else {
1588                 float obmat[4][4];
1589
1590                 BKE_tracking_get_interpolated_camera(tracking, tracking_object, scene->r.cfra, obmat);
1591
1592                 invert_m4_m4(imat, obmat);
1593                 glMultMatrixf(imat);
1594         }
1595
1596         for (track = tracksbase->first; track; track = track->next) {
1597                 int selected = TRACK_SELECTED(track);
1598
1599                 if (draw_selected && !selected)
1600                         continue;
1601
1602                 if ((track->flag & TRACK_HAS_BUNDLE) == 0)
1603                         continue;
1604
1605                 if (flag & DRAW_PICKING)
1606                         glLoadName(base->selcol + (tracknr << 16));
1607
1608                 glPushMatrix();
1609                 glTranslatef(track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
1610                 glScalef(v3d->bundle_size / 0.05f, v3d->bundle_size / 0.05f, v3d->bundle_size / 0.05f);
1611
1612                 if (v3d->drawtype == OB_WIRE) {
1613                         glDisable(GL_LIGHTING);
1614
1615                         if (selected) {
1616                                 if (base == BASACT) UI_ThemeColor(TH_ACTIVE);
1617                                 else UI_ThemeColor(TH_SELECT);
1618                         }
1619                         else {
1620                                 if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1621                                 else UI_ThemeColor(TH_WIRE);
1622                         }
1623
1624                         drawaxes(0.05f, v3d->bundle_drawtype);
1625
1626                         glEnable(GL_LIGHTING);
1627                 }
1628                 else if (v3d->drawtype > OB_WIRE) {
1629                         if (v3d->bundle_drawtype == OB_EMPTY_SPHERE) {
1630                                 /* selection outline */
1631                                 if (selected) {
1632                                         if (base == BASACT) UI_ThemeColor(TH_ACTIVE);
1633                                         else UI_ThemeColor(TH_SELECT);
1634
1635                                         glLineWidth(2.f);
1636                                         glDisable(GL_LIGHTING);
1637                                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1638
1639                                         draw_bundle_sphere();
1640
1641                                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1642                                         glEnable(GL_LIGHTING);
1643                                         glLineWidth(1.f);
1644                                 }
1645
1646                                 if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1647                                 else UI_ThemeColor(TH_BUNDLE_SOLID);
1648
1649                                 draw_bundle_sphere();
1650                         }
1651                         else {
1652                                 glDisable(GL_LIGHTING);
1653
1654                                 if (selected) {
1655                                         if (base == BASACT) UI_ThemeColor(TH_ACTIVE);
1656                                         else UI_ThemeColor(TH_SELECT);
1657                                 }
1658                                 else {
1659                                         if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1660                                         else UI_ThemeColor(TH_WIRE);
1661                                 }
1662
1663                                 drawaxes(0.05f, v3d->bundle_drawtype);
1664
1665                                 glEnable(GL_LIGHTING);
1666                         }
1667                 }
1668
1669                 glPopMatrix();
1670
1671                 if ((flag & DRAW_PICKING) == 0 && (v3d->flag2 & V3D_SHOW_BUNDLENAME)) {
1672                         float pos[3];
1673                         unsigned char tcol[4];
1674
1675                         if (selected) memcpy(tcol, scol, sizeof(tcol));
1676                         else memcpy(tcol, col, sizeof(tcol));
1677
1678                         mul_v3_m4v3(pos, mat, track->bundle_pos);
1679                         view3d_cached_text_draw_add(pos, track->name, 10, V3D_CACHE_TEXT_GLOBALSPACE, tcol);
1680                 }
1681
1682                 tracknr++;
1683         }
1684
1685         if ((flag & DRAW_PICKING) == 0) {
1686                 if ((v3d->flag2 & V3D_SHOW_CAMERAPATH) && (tracking_object->flag & TRACKING_OBJECT_CAMERA)) {
1687                         MovieTrackingReconstruction *reconstruction;
1688                         reconstruction = BKE_tracking_object_reconstruction(tracking, tracking_object);
1689
1690                         if (reconstruction->camnr) {
1691                                 MovieReconstructedCamera *camera = reconstruction->cameras;
1692                                 int a = 0;
1693
1694                                 glDisable(GL_LIGHTING);
1695                                 UI_ThemeColor(TH_CAMERA_PATH);
1696                                 glLineWidth(2.0f);
1697
1698                                 glBegin(GL_LINE_STRIP);
1699                                 for (a = 0; a < reconstruction->camnr; a++, camera++) {
1700                                         glVertex3fv(camera->mat[3]);
1701                                 }
1702                                 glEnd();
1703
1704                                 glLineWidth(1.0f);
1705                                 glEnable(GL_LIGHTING);
1706                         }
1707                 }
1708         }
1709
1710         glPopMatrix();
1711
1712         *global_track_index = tracknr;
1713 }
1714
1715 static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, MovieClip *clip,
1716                                          int flag, const unsigned char ob_wire_col[4],
1717                                          int draw_selected)
1718 {
1719         MovieTracking *tracking = &clip->tracking;
1720         MovieTrackingObject *tracking_object;
1721         int global_track_index = 1;
1722
1723         if ((v3d->flag2 & V3D_SHOW_RECONSTRUCTION) == 0)
1724                 return;
1725
1726         if (v3d->flag2 & V3D_RENDER_OVERRIDE)
1727                 return;
1728
1729         glEnable(GL_LIGHTING);
1730         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1731         glEnable(GL_COLOR_MATERIAL);
1732         glShadeModel(GL_SMOOTH);
1733
1734         tracking_object = tracking->objects.first;
1735         while (tracking_object) {
1736                 draw_viewport_object_reconstruction(scene, base, v3d, clip, tracking_object,
1737                                                     flag, &global_track_index, draw_selected);
1738
1739                 tracking_object = tracking_object->next;
1740         }
1741
1742         /* restore */
1743         glShadeModel(GL_FLAT);
1744         glDisable(GL_COLOR_MATERIAL);
1745         glDisable(GL_LIGHTING);
1746
1747         glColor3ubv(ob_wire_col);
1748
1749         if (flag & DRAW_PICKING)
1750                 glLoadName(base->selcol);
1751 }
1752
1753 /* flag similar to draw_object() */
1754 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
1755                        int flag, const unsigned char ob_wire_col[4])
1756 {
1757         /* a standing up pyramid with (0,0,0) as top */
1758         Camera *cam;
1759         Object *ob = base->object;
1760         float tvec[3];
1761         float vec[4][3], asp[2], shift[2], scale[3];
1762         int i;
1763         float drawsize;
1764         const short is_view = (rv3d->persp == RV3D_CAMOB && ob == v3d->camera);
1765         MovieClip *clip = BKE_object_movieclip_get(scene, base->object, 0);
1766
1767         /* draw data for movie clip set as active for scene */
1768         if (clip) {
1769                 draw_viewport_reconstruction(scene, base, v3d, clip, flag, ob_wire_col, FALSE);
1770                 draw_viewport_reconstruction(scene, base, v3d, clip, flag, ob_wire_col, TRUE);
1771         }
1772
1773 #ifdef VIEW3D_CAMERA_BORDER_HACK
1774         if (is_view && !(G.f & G_PICKSEL)) {
1775                 view3d_camera_border_hack_col[0] = ob_wire_col[0];
1776                 view3d_camera_border_hack_col[1] = ob_wire_col[1];
1777                 view3d_camera_border_hack_col[2] = ob_wire_col[2];
1778                 view3d_camera_border_hack_test = TRUE;
1779                 return;
1780         }
1781 #endif
1782
1783         cam = ob->data;
1784
1785         scale[0] = 1.0f / len_v3(ob->obmat[0]);
1786         scale[1] = 1.0f / len_v3(ob->obmat[1]);
1787         scale[2] = 1.0f / len_v3(ob->obmat[2]);
1788
1789         BKE_camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale,
1790                                  asp, shift, &drawsize, vec);
1791
1792         glDisable(GL_LIGHTING);
1793         glDisable(GL_CULL_FACE);
1794
1795         /* camera frame */
1796         glBegin(GL_LINE_LOOP);
1797         glVertex3fv(vec[0]);
1798         glVertex3fv(vec[1]);
1799         glVertex3fv(vec[2]);
1800         glVertex3fv(vec[3]);
1801         glEnd();
1802
1803         if (is_view)
1804                 return;
1805
1806         zero_v3(tvec);
1807
1808         /* center point to camera frame */
1809         glBegin(GL_LINE_STRIP);
1810         glVertex3fv(vec[1]);
1811         glVertex3fv(tvec);
1812         glVertex3fv(vec[0]);
1813         glVertex3fv(vec[3]);
1814         glVertex3fv(tvec);
1815         glVertex3fv(vec[2]);
1816         glEnd();
1817
1818
1819         /* arrow on top */
1820         tvec[2] = vec[1][2]; /* copy the depth */
1821
1822
1823         /* draw an outline arrow for inactive cameras and filled
1824          * for active cameras. We actually draw both outline+filled
1825          * for active cameras so the wire can be seen side-on */
1826         for (i = 0; i < 2; i++) {
1827                 if (i == 0) glBegin(GL_LINE_LOOP);
1828                 else if (i == 1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1829                 else break;
1830
1831                 tvec[0] = shift[0] + ((-0.7f * drawsize) * scale[0]);
1832                 tvec[1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]);
1833                 glVertex3fv(tvec); /* left */
1834                 
1835                 tvec[0] = shift[0] + ((0.7f * drawsize) * scale[0]);
1836                 glVertex3fv(tvec); /* right */
1837                 
1838                 tvec[0] = shift[0];
1839                 tvec[1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
1840                 glVertex3fv(tvec); /* top */
1841
1842                 glEnd();
1843         }
1844
1845         if (flag == 0) {
1846                 if (cam->flag & (CAM_SHOWLIMITS + CAM_SHOWMIST)) {
1847                         float nobmat[4][4];
1848                         World *wrld;
1849
1850                         /* draw in normalized object matrix space */
1851                         copy_m4_m4(nobmat, ob->obmat);
1852                         normalize_m4(nobmat);
1853
1854                         glPushMatrix();
1855                         glLoadMatrixf(rv3d->viewmat);
1856                         glMultMatrixf(nobmat);
1857
1858                         if (cam->flag & CAM_SHOWLIMITS) {
1859                                 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1860                                 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composite node */
1861                                 draw_focus_cross(BKE_camera_object_dof_distance(ob), cam->drawsize);
1862                         }
1863
1864                         wrld = scene->world;
1865                         if (cam->flag & CAM_SHOWMIST)
1866                                 if (wrld) draw_limit_line(wrld->miststa, wrld->miststa + wrld->mistdist, 0xFFFFFF);
1867
1868                         glPopMatrix();
1869                 }
1870         }
1871 }
1872
1873 /* flag similar to draw_object() */
1874 static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d),
1875                         Object *UNUSED(ob), int UNUSED(flag))
1876 {
1877         //Speaker *spk = ob->data;
1878
1879         float vec[3];
1880         int i, j;
1881
1882         glEnable(GL_BLEND);
1883
1884         for (j = 0; j < 3; j++) {
1885                 vec[2] = 0.25f * j - 0.125f;
1886
1887                 glBegin(GL_LINE_LOOP);
1888                 for (i = 0; i < 16; i++) {
1889                         vec[0] = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1890                         vec[1] = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1891                         glVertex3fv(vec);
1892                 }
1893                 glEnd();
1894         }
1895
1896         for (j = 0; j < 4; j++) {
1897                 vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f;
1898                 vec[1] = ((j % 2) * (j - 2)) * 0.5f;
1899                 glBegin(GL_LINE_STRIP);
1900                 for (i = 0; i < 3; i++) {
1901                         if (i == 1) {
1902                                 vec[0] *= 0.5f;
1903                                 vec[1] *= 0.5f;
1904                         }
1905
1906                         vec[2] = 0.25f * i - 0.125f;
1907                         glVertex3fv(vec);
1908                 }
1909                 glEnd();
1910         }
1911
1912         glDisable(GL_BLEND);
1913 }
1914
1915 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1916 {
1917         BPoint *bp = lt->def;
1918         float *co = dl ? dl->verts : NULL;
1919         int u, v, w;
1920
1921         UI_ThemeColor(sel ? TH_VERTEX_SELECT : TH_VERTEX);
1922         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1923         bglBegin(GL_POINTS);
1924
1925         for (w = 0; w < lt->pntsw; w++) {
1926                 int wxt = (w == 0 || w == lt->pntsw - 1);
1927                 for (v = 0; v < lt->pntsv; v++) {
1928                         int vxt = (v == 0 || v == lt->pntsv - 1);
1929                         for (u = 0; u < lt->pntsu; u++, bp++, co += 3) {
1930                                 int uxt = (u == 0 || u == lt->pntsu - 1);
1931                                 if (!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1932                                         if (bp->hide == 0) {
1933                                                 if ((bp->f1 & SELECT) == sel) {
1934                                                         bglVertex3fv(dl ? co : bp->vec);
1935                                                 }
1936                                         }
1937                                 }
1938                         }
1939                 }
1940         }
1941         
1942         glPointSize(1.0);
1943         bglEnd();
1944 }
1945
1946 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1947 {
1948         Object *obedit = vc->obedit;
1949         Lattice *lt = obedit->data;
1950         BPoint *bp = lt->editlatt->latt->def;
1951         DispList *dl = BKE_displist_find(&obedit->disp, DL_VERTS);
1952         float *co = dl ? dl->verts : NULL;
1953         int i, N = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
1954         short s[2] = {IS_CLIPPED, 0};
1955
1956         ED_view3d_clipping_local(vc->rv3d, obedit->obmat); /* for local clipping lookups */
1957
1958         for (i = 0; i < N; i++, bp++, co += 3) {
1959                 if (bp->hide == 0) {
1960                         view3d_project_short_clip(vc->ar, dl ? co : bp->vec, s, TRUE);
1961                         if (s[0] != IS_CLIPPED)
1962                                 func(userData, bp, s[0], s[1]);
1963                 }
1964         }
1965 }
1966
1967 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1968 {
1969         int index = ((w * lt->pntsv + v) * lt->pntsu) + u;
1970
1971         if (use_wcol) {
1972                 float col[3];
1973                 MDeformWeight *mdw = defvert_find_index(lt->dvert + index, use_wcol - 1);
1974                 
1975                 weight_to_rgb(col, mdw ? mdw->weight : 0.0f);
1976                 glColor3fv(col);
1977
1978         }
1979         
1980         if (dl) {
1981                 glVertex3fv(&dl->verts[index * 3]);
1982         }
1983         else {
1984                 glVertex3fv(lt->def[index].vec);
1985         }
1986 }
1987
1988 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1989 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1990 {
1991         Lattice *lt = ob->data;
1992         DispList *dl;
1993         int u, v, w;
1994         int use_wcol = FALSE, is_edit = (lt->editlatt != NULL);
1995
1996         /* now we default make displist, this will modifiers work for non animated case */
1997         if (ob->disp.first == NULL)
1998                 BKE_lattice_modifiers_calc(scene, ob);
1999         dl = BKE_displist_find(&ob->disp, DL_VERTS);
2000         
2001         if (is_edit) {
2002                 lt = lt->editlatt->latt;
2003
2004                 cpack(0x004000);
2005                 
2006                 if (ob->defbase.first && lt->dvert) {
2007                         use_wcol = ob->actdef;
2008                         glShadeModel(GL_SMOOTH);
2009                 }
2010         }
2011         
2012         glBegin(GL_LINES);
2013         for (w = 0; w < lt->pntsw; w++) {
2014                 int wxt = (w == 0 || w == lt->pntsw - 1);
2015                 for (v = 0; v < lt->pntsv; v++) {
2016                         int vxt = (v == 0 || v == lt->pntsv - 1);
2017                         for (u = 0; u < lt->pntsu; u++) {
2018                                 int uxt = (u == 0 || u == lt->pntsu - 1);
2019
2020                                 if (w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
2021                                         drawlattice__point(lt, dl, u, v, w - 1, use_wcol);
2022                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
2023                                 }
2024                                 if (v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
2025                                         drawlattice__point(lt, dl, u, v - 1, w, use_wcol);
2026                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
2027                                 }
2028                                 if (u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
2029                                         drawlattice__point(lt, dl, u - 1, v, w, use_wcol);
2030                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
2031                                 }
2032                         }
2033                 }
2034         }
2035         glEnd();
2036         
2037         /* restoration for weight colors */
2038         if (use_wcol)
2039                 glShadeModel(GL_FLAT);
2040
2041         if (is_edit) {
2042                 if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
2043                 
2044                 lattice_draw_verts(lt, dl, 0);
2045                 lattice_draw_verts(lt, dl, 1);
2046                 
2047                 if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
2048         }
2049 }
2050
2051 /* ***************** ******************** */
2052
2053 /* Note! - foreach funcs should be called while drawing or directly after
2054  * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
2055  * but would not give correct results with dupli's for eg. which don't
2056  * use the object matrix in the usual way */
2057 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, const float co[3],
2058                                             const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2059 {
2060         foreachScreenVert_userData *data = userData;
2061         BMVert *eve = EDBM_vert_at_index(data->vc.em, index);
2062
2063         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
2064                 short s[2] = {IS_CLIPPED, 0};
2065
2066                 if (data->clipVerts != V3D_CLIP_TEST_OFF) {
2067                         view3d_project_short_clip(data->vc.ar, co, s, TRUE);
2068                 }
2069                 else {
2070                         float co2[2];
2071                         mul_v3_m4v3(co2, data->vc.obedit->obmat, co);
2072                         project_short_noclip(data->vc.ar, co2, s);
2073                 }
2074
2075                 if (s[0] != IS_CLIPPED)
2076                         data->func(data->userData, eve, s[0], s[1], index);
2077         }
2078 }
2079
2080 void mesh_foreachScreenVert(
2081         ViewContext *vc,
2082         void (*func)(void *userData, BMVert *eve, int x, int y, int index),
2083         void *userData, eV3DClipTest clipVerts)
2084 {
2085         foreachScreenVert_userData data;
2086         DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2087         
2088         data.vc = *vc;
2089         data.func = func;
2090         data.userData = userData;
2091         data.clipVerts = clipVerts;
2092
2093         if (clipVerts != V3D_CLIP_TEST_OFF)
2094                 ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat);  /* for local clipping lookups */
2095
2096         EDBM_index_arrays_init(vc->em, 1, 0, 0);
2097         dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
2098         EDBM_index_arrays_free(vc->em);
2099
2100         dm->release(dm);
2101 }
2102
2103 /*  draw callback */
2104 static void drawSelectedVertices__mapFunc(void *userData, int index, const float co[3],
2105                                           const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2106 {
2107         MVert *mv = &((MVert *)userData)[index];
2108
2109         if (!(mv->flag & ME_HIDE)) {
2110                 const char sel = mv->flag & SELECT;
2111
2112                 // TODO define selected color
2113                 if (sel) {
2114                         glColor3f(1.0f, 1.0f, 0.0f);
2115                 }
2116                 else {
2117                         glColor3f(0.0f, 0.0f, 0.0f);
2118                 }
2119
2120                 glVertex3fv(co);
2121         }
2122 }
2123
2124 static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
2125 {
2126         glBegin(GL_POINTS);
2127         dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, me->mvert);
2128         glEnd();
2129 }
2130
2131 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, const float v0co[3], const float v1co[3])
2132 {
2133         foreachScreenEdge_userData *data = userData;
2134         BMEdge *eed = EDBM_edge_at_index(data->vc.em, index);
2135
2136         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
2137                 short s[2][2];
2138
2139                 if (data->clipVerts == V3D_CLIP_TEST_RV3D_CLIPPING) {
2140                         view3d_project_short_clip(data->vc.ar, v0co, s[0], TRUE);
2141                         view3d_project_short_clip(data->vc.ar, v1co, s[1], TRUE);
2142                 }
2143                 else {
2144                         float v1_co[3], v2_co[3];
2145
2146                         mul_v3_m4v3(v1_co, data->vc.obedit->obmat, v0co);
2147                         mul_v3_m4v3(v2_co, data->vc.obedit->obmat, v1co);
2148
2149                         project_short_noclip(data->vc.ar, v1_co, s[0]);
2150                         project_short_noclip(data->vc.ar, v2_co, s[1]);
2151
2152                         if (data->clipVerts == V3D_CLIP_TEST_REGION) {
2153                                 /* make an int copy */
2154                                 int s_int[2][2] = {{s[0][0], s[0][1]},
2155                                                    {s[1][0], s[1][1]}};
2156                                 if (!BLI_segment_in_rcti(&data->win_rect, s_int[0], s_int[1])) {
2157                                         return;
2158                                 }
2159                         }
2160                 }
2161
2162                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
2163         }
2164 }
2165
2166 void mesh_foreachScreenEdge(
2167         ViewContext *vc,
2168         void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index),
2169         void *userData, eV3DClipTest clipVerts)
2170 {
2171         foreachScreenEdge_userData data;
2172         DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2173
2174         data.vc = *vc;
2175
2176         data.win_rect.xmin = 0;
2177         data.win_rect.ymin = 0;
2178         data.win_rect.xmax = vc->ar->winx;
2179         data.win_rect.ymax = vc->ar->winy;
2180
2181         data.func = func;
2182         data.userData = userData;
2183         data.clipVerts = clipVerts;
2184
2185         if (clipVerts != V3D_CLIP_TEST_OFF)
2186                 ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat);  /* for local clipping lookups */
2187
2188         EDBM_index_arrays_init(vc->em, 0, 1, 0);
2189         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
2190         EDBM_index_arrays_free(vc->em);
2191
2192         dm->release(dm);
2193 }
2194
2195 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3]))
2196 {
2197         foreachScreenFace_userData *data = userData;
2198         BMFace *efa = EDBM_face_at_index(data->vc.em, index);
2199
2200         if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2201                 float cent2[3];
2202                 short s[2];
2203
2204                 mul_v3_m4v3(cent2, data->vc.obedit->obmat, cent);
2205                 project_short(data->vc.ar, cent2, s);
2206
2207                 if (s[0] != IS_CLIPPED) {
2208                         data->func(data->userData, efa, s[0], s[1], index);
2209                 }
2210         }
2211 }
2212
2213 void mesh_foreachScreenFace(
2214         ViewContext *vc,
2215         void (*func)(void *userData, BMFace *efa, int x, int y, int index),
2216         void *userData)
2217 {
2218         foreachScreenFace_userData data;
2219         DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2220
2221         data.vc = *vc;
2222         data.func = func;
2223         data.userData = userData;
2224
2225         //if (clipVerts)
2226         ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2227
2228         EDBM_index_arrays_init(vc->em, 0, 0, 1);
2229         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
2230         EDBM_index_arrays_free(vc->em);
2231
2232         dm->release(dm);
2233 }
2234
2235 void nurbs_foreachScreenVert(
2236     ViewContext *vc,
2237     void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y),
2238     void *userData)
2239 {
2240         Curve *cu = vc->obedit->data;
2241         short s[2] = {IS_CLIPPED, 0};
2242         Nurb *nu;
2243         int i;
2244         ListBase *nurbs = BKE_curve_editNurbs_get(cu);
2245
2246         ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2247
2248         for (nu = nurbs->first; nu; nu = nu->next) {
2249                 if (nu->type == CU_BEZIER) {
2250                         for (i = 0; i < nu->pntsu; i++) {
2251                                 BezTriple *bezt = &nu->bezt[i];
2252
2253                                 if (bezt->hide == 0) {
2254                                         
2255                                         if (cu->drawflag & CU_HIDE_HANDLES) {
2256                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, TRUE);
2257                                                 if (s[0] != IS_CLIPPED)
2258                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
2259                                         }
2260                                         else {
2261                                                 view3d_project_short_clip(vc->ar, bezt->vec[0], s, TRUE);
2262                                                 if (s[0] != IS_CLIPPED)
2263                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
2264                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, TRUE);
2265                                                 if (s[0] != IS_CLIPPED)
2266                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
2267                                                 view3d_project_short_clip(vc->ar, bezt->vec[2], s, TRUE);
2268                                                 if (s[0] != IS_CLIPPED)
2269                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
2270                                         }
2271                                 }
2272                         }
2273                 }
2274                 else {
2275                         for (i = 0; i < nu->pntsu * nu->pntsv; i++) {
2276                                 BPoint *bp = &nu->bp[i];
2277
2278                                 if (bp->hide == 0) {
2279                                         view3d_project_short_clip(vc->ar, bp->vec, s, TRUE);
2280                                         if (s[0] != IS_CLIPPED)
2281                                                 func(userData, nu, bp, NULL, -1, s[0], s[1]);
2282                                 }
2283                         }
2284                 }
2285         }
2286 }
2287
2288 /* ************** DRAW MESH ****************** */
2289
2290 /* First section is all the "simple" draw routines, 
2291  * ones that just pass some sort of primitive to GL,
2292  * with perhaps various options to control lighting,
2293  * color, etc.
2294  *
2295  * These routines should not have user interface related
2296  * logic!!!
2297  */
2298
2299 static void calcDrawDMNormalScale(Object *ob, drawDMNormal_userData *data)
2300 {
2301         float obmat[3][3];
2302
2303         copy_m3_m4(obmat, ob->obmat);
2304
2305         data->uniform_scale = is_uniform_scaled_m3(obmat);
2306
2307         if (!data->uniform_scale) {
2308                 /* inverted matrix */
2309                 invert_m3_m3(data->imat, obmat);
2310
2311                 /* transposed inverted matrix */
2312                 copy_m3_m3(data->tmat, data->imat);
2313                 transpose_m3(data->tmat);
2314         }
2315 }
2316
2317 static void draw_dm_face_normals__mapFunc(void *userData, int index, const float cent[3], const float no[3])
2318 {
2319         drawDMNormal_userData *data = userData;
2320         BMFace *efa = EDBM_face_at_index(data->em, index);
2321         float n[3];
2322
2323         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2324                 if (!data->uniform_scale) {
2325                         mul_v3_m3v3(n, data->tmat, (float *) no);
2326                         normalize_v3(n);
2327                         mul_m3_v3(data->imat, n);
2328                 }
2329                 else {
2330                         copy_v3_v3(n, no);
2331                 }
2332
2333                 glVertex3fv(cent);
2334                 glVertex3f(cent[0] + n[0] * data->normalsize,
2335                            cent[1] + n[1] * data->normalsize,
2336                            cent[2] + n[2] * data->normalsize);
2337         }
2338 }
2339
2340 static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
2341 {
2342         drawDMNormal_userData data;
2343
2344         data.em = em;
2345         data.normalsize = scene->toolsettings->normalsize;
2346
2347         calcDrawDMNormalScale(ob, &data);
2348
2349         glBegin(GL_LINES);
2350         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, &data);
2351         glEnd();
2352 }
2353
2354 static void draw_dm_face_centers__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3]))
2355 {
2356         BMFace *efa = EDBM_face_at_index(((void **)userData)[0], index);
2357         int sel = *(((int **)userData)[1]);
2358         
2359         if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BM_elem_flag_test(efa, BM_ELEM_SELECT) == sel) {
2360                 bglVertex3fv(cent);
2361         }
2362 }
2363 static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, int sel)
2364 {
2365         void *ptrs[2] = {em, &sel};
2366
2367         bglBegin(GL_POINTS);
2368         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, ptrs);
2369         bglEnd();
2370 }
2371
2372 static void draw_dm_vert_normals__mapFunc(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3])
2373 {
2374         drawDMNormal_userData *data = userData;
2375         BMVert *eve = EDBM_vert_at_index(data->em, index);
2376
2377         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
2378                 float no[3], n[3];
2379
2380                 if (no_f) {
2381                         copy_v3_v3(no, no_f);
2382                 }
2383                 else {
2384                         no[0] = no_s[0] / 32767.0f;
2385                         no[1] = no_s[1] / 32767.0f;
2386                         no[2] = no_s[2] / 32767.0f;
2387                 }
2388
2389                 if (!data->uniform_scale) {
2390                         mul_v3_m3v3(n, data->tmat, (float *) no);
2391                         normalize_v3(n);
2392                         mul_m3_v3(data->imat, n);
2393                 }
2394                 else {
2395                         copy_v3_v3(n, no);
2396                 }
2397
2398                 glVertex3fv(co);
2399                 glVertex3f(co[0] + n[0] * data->normalsize,
2400                            co[1] + n[1] * data->normalsize,
2401                            co[2] + n[2] * data->normalsize);
2402         }
2403 }
2404
2405 static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
2406 {
2407         drawDMNormal_userData data;
2408
2409         data.em = em;
2410         data.normalsize = scene->toolsettings->normalsize;
2411
2412         calcDrawDMNormalScale(ob, &data);
2413
2414         glBegin(GL_LINES);
2415         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, &data);
2416         glEnd();
2417 }
2418
2419 /* Draw verts with color set based on selection */
2420 static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3],
2421                                    const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2422 {
2423         drawDMVerts_userData *data = userData;
2424         BMVert *eve = EDBM_vert_at_index(data->em, index);
2425
2426         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->sel) {
2427                 /* skin nodes: draw a red circle around the root
2428                  * node(s) */
2429                 if (data->has_vskin) {
2430                         const MVertSkin *vs = CustomData_bmesh_get(&data->em->bm->vdata,
2431                                                                    eve->head.data,
2432                                                                    CD_MVERT_SKIN);
2433                         if (vs->flag & MVERT_SKIN_ROOT) {
2434                                 float radius = (vs->radius[0] + vs->radius[1]) * 0.5f;
2435                                 bglEnd();
2436                         
2437                                 glColor4ubv(data->th_skin_root);
2438                                 drawcircball(GL_LINES, co, radius, data->imat);
2439
2440                                 glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex);
2441                                 bglBegin(GL_POINTS);
2442                         }
2443                 }
2444
2445                 /* draw active larger - need to stop/start point drawing for this :/ */
2446                 if (eve == data->eve_act) {
2447                         glColor4ubv(data->th_editmesh_active);
2448                         
2449                         bglEnd();
2450                         
2451                         glPointSize(data->th_vertex_size);
2452                         bglBegin(GL_POINTS);
2453                         bglVertex3fv(co);
2454                         bglEnd();
2455
2456                         glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex);
2457                         glPointSize(data->th_vertex_size);
2458                         bglBegin(GL_POINTS);
2459                 }
2460                 else {
2461                         bglVertex3fv(co);
2462                 }
2463         }
2464 }
2465
2466 static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, int sel, BMVert *eve_act,
2467                           RegionView3D *rv3d)
2468 {
2469         drawDMVerts_userData data;
2470         data.sel = sel;
2471         data.eve_act = eve_act;
2472         data.em = em;
2473
2474         /* Cache theme values */
2475         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, data.th_editmesh_active);
2476         UI_GetThemeColor4ubv(TH_VERTEX_SELECT, data.th_vertex_select);
2477         UI_GetThemeColor4ubv(TH_VERTEX, data.th_vertex);
2478         UI_GetThemeColor4ubv(TH_SKIN_ROOT, data.th_skin_root);
2479         data.th_vertex_size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2480
2481         /* For skin root drawing */
2482         data.has_vskin = CustomData_has_layer(&em->bm->vdata, CD_MVERT_SKIN);
2483         /* view-aligned matrix */
2484         mult_m4_m4m4(data.imat, rv3d->viewmat, em->ob->obmat);
2485         invert_m4(data.imat);
2486
2487         bglBegin(GL_POINTS);
2488         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
2489         bglEnd();
2490 }
2491
2492 /* Draw edges with color set based on selection */
2493 static DMDrawOption draw_dm_edges_sel__setDrawOptions(void *userData, int index)
2494 {
2495         BMEdge *eed;
2496         //unsigned char **cols = userData, *col;
2497         drawDMEdgesSel_userData *data = userData;
2498         unsigned char *col;
2499
2500         eed = EDBM_edge_at_index(data->em, index);
2501
2502         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
2503                 if (eed == data->eed_act) {
2504                         glColor4ubv(data->actCol);
2505                 }
2506                 else {
2507                         if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
2508                                 col = data->selCol;
2509                         }
2510                         else {
2511                                 col = data->baseCol;
2512                         }
2513                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
2514                         if (col[3] == 0)
2515                                 return DM_DRAW_OPTION_SKIP;
2516                         
2517                         glColor4ubv(col);
2518                 }
2519                 return DM_DRAW_OPTION_NORMAL;
2520         }
2521         else {
2522                 return DM_DRAW_OPTION_SKIP;
2523         }
2524 }
2525 static void draw_dm_edges_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, 
2526                               unsigned char *selCol, unsigned char *actCol, BMEdge *eed_act)
2527 {
2528         drawDMEdgesSel_userData data;
2529         
2530         data.baseCol = baseCol;
2531         data.selCol = selCol;
2532         data.actCol = actCol;
2533         data.em = em;
2534         data.eed_act = eed_act;
2535         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
2536 }
2537
2538 /* Draw edges */
2539 static DMDrawOption draw_dm_edges__setDrawOptions(void *userData, int index)
2540 {
2541         if (BM_elem_flag_test(EDBM_edge_at_index(userData, index), BM_ELEM_HIDDEN))
2542                 return DM_DRAW_OPTION_SKIP;
2543         else
2544                 return DM_DRAW_OPTION_NORMAL;
2545 }
2546
2547 static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm) 
2548 {
2549         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, em);
2550 }
2551
2552 /* Draw edges with color interpolated based on selection */
2553 static DMDrawOption draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
2554 {
2555         if (BM_elem_flag_test(EDBM_edge_at_index(((void **)userData)[0], index), BM_ELEM_HIDDEN))
2556                 return DM_DRAW_OPTION_SKIP;
2557         else
2558                 return DM_DRAW_OPTION_NORMAL;
2559 }
2560 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2561 {
2562         BMEdge *eed = EDBM_edge_at_index(((void **)userData)[0], index);
2563         unsigned char **cols = userData;
2564         unsigned char *col0 = cols[(BM_elem_flag_test(eed->v1, BM_ELEM_SELECT)) ? 2 : 1];
2565         unsigned char *col1 = cols[(BM_elem_flag_test(eed->v2, BM_ELEM_SELECT)) ? 2 : 1];
2566
2567         glColor4ub(col0[0] + (col1[0] - col0[0]) * t,
2568                    col0[1] + (col1[1] - col0[1]) * t,
2569                    col0[2] + (col1[2] - col0[2]) * t,
2570                    col0[3] + (col1[3] - col0[3]) * t);
2571 }
2572
2573 static void draw_dm_edges_sel_interp(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2574 {
2575         void *cols[3] = {em, baseCol, selCol};
2576
2577         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2578 }
2579
2580 /* Draw only seam edges */
2581 static DMDrawOption draw_dm_edges_seams__setDrawOptions(void *userData, int index)
2582 {
2583         BMEdge *eed = EDBM_edge_at_index(userData, index);
2584
2585         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BM_elem_flag_test(eed, BM_ELEM_SEAM))
2586                 return DM_DRAW_OPTION_NORMAL;
2587         else
2588                 return DM_DRAW_OPTION_SKIP;
2589 }
2590
2591 static void draw_dm_edges_seams(BMEditMesh *em, DerivedMesh *dm)
2592 {
2593         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, em);
2594 }
2595
2596 /* Draw only sharp edges */
2597 static DMDrawOption draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
2598 {
2599         BMEdge *eed = EDBM_edge_at_index(userData, index);
2600
2601         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && !BM_elem_flag_test(eed, BM_ELEM_SMOOTH))
2602                 return DM_DRAW_OPTION_NORMAL;
2603         else
2604                 return DM_DRAW_OPTION_SKIP;
2605 }
2606
2607 static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm)
2608 {
2609         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, em);
2610 }
2611
2612
2613 /* Draw faces with color set based on selection
2614  * return 2 for the active face so it renders with stipple enabled */
2615 static DMDrawOption draw_dm_faces_sel__setDrawOptions(void *userData, int index)
2616 {
2617         drawDMFacesSel_userData *data = userData;
2618         BMFace *efa = EDBM_face_at_index(data->em, index);
2619         unsigned char *col;
2620         
2621         if (!efa)
2622                 return DM_DRAW_OPTION_SKIP;
2623         
2624         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2625                 if (efa == data->efa_act) {
2626                         glColor4ubv(data->cols[2]);
2627                         return DM_DRAW_OPTION_STIPPLE;
2628                 }
2629                 else {
2630                         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
2631                         if (col[3] == 0)
2632                                 return DM_DRAW_OPTION_SKIP;
2633                         glColor4ubv(col);
2634                         return DM_DRAW_OPTION_NORMAL;
2635                 }
2636         }
2637         return DM_DRAW_OPTION_SKIP;
2638 }
2639
2640 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2641 {
2642
2643         drawDMFacesSel_userData *data = userData;
2644         BMFace *efa;
2645         BMFace *next_efa;
2646
2647         unsigned char *col, *next_col;
2648
2649         if (!data->orig_index)
2650                 return 0;
2651
2652         efa = EDBM_face_at_index(data->em, data->orig_index[index]);
2653         next_efa = EDBM_face_at_index(data->em, data->orig_index[next_index]);
2654
2655         if (efa == next_efa)
2656                 return 1;
2657
2658         if (efa == data->efa_act || next_efa == data->efa_act)
2659                 return 0;
2660
2661         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
2662         next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT) ? 1 : 0];
2663
2664         if (col[3] == 0 || next_col[3] == 0)
2665                 return 0;
2666
2667         return col == next_col;
2668 }
2669
2670 /* also draws the active face */
2671 static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, 
2672                               unsigned char *selCol, unsigned char *actCol, BMFace *efa_act)
2673 {
2674         drawDMFacesSel_userData data;
2675         data.dm = dm;
2676         data.cols[0] = baseCol;
2677         data.em = em;
2678         data.cols[1] = selCol;
2679         data.cols[2] = actCol;
2680         data.efa_act = efa_act;
2681         data.orig_index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
2682
2683         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0);
2684 }
2685
2686 static DMDrawOption draw_dm_creases__setDrawOptions(void *userData, int index)
2687 {
2688         BMEditMesh *em = userData;
2689         BMEdge *eed = EDBM_edge_at_index(userData, index);
2690         float *crease = eed ? (float *)CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_CREASE) : NULL;
2691         
2692         if (!crease)
2693                 return DM_DRAW_OPTION_SKIP;
2694         
2695         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && *crease != 0.0f) {
2696                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, *crease);
2697                 return DM_DRAW_OPTION_NORMAL;
2698         }
2699         else {
2700                 return DM_DRAW_OPTION_SKIP;
2701         }
2702 }
2703 static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm)
2704 {
2705         glLineWidth(3.0);
2706         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, em);
2707         glLineWidth(1.0);
2708 }
2709
2710 static DMDrawOption draw_dm_bweights__setDrawOptions(void *userData, int index)
2711 {
2712         BMEditMesh *em = userData;
2713         BMEdge *eed = EDBM_edge_at_index(userData, index);
2714         float *bweight = (float *)CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_BWEIGHT);
2715
2716         if (!bweight)
2717                 return DM_DRAW_OPTION_SKIP;
2718         
2719         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && *bweight != 0.0f) {
2720                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, *bweight);
2721                 return DM_DRAW_OPTION_NORMAL;
2722         }
2723         else {
2724                 return DM_DRAW_OPTION_SKIP;
2725         }
2726 }
2727 static void draw_dm_bweights__mapFunc(void *userData, int index, const float co[3],
2728                                       const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2729 {
2730         BMEditMesh *em = userData;
2731         BMVert *eve = EDBM_vert_at_index(userData, index);
2732         float *bweight = (float *)CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_BWEIGHT);
2733         
2734         if (!bweight)
2735                 return;
2736         
2737         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && *bweight != 0.0f) {
2738                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, *bweight);
2739                 bglVertex3fv(co);
2740         }
2741 }
2742 static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
2743 {
2744         ToolSettings *ts = scene->toolsettings;
2745
2746         if (ts->selectmode & SCE_SELECT_VERTEX) {
2747                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2748                 bglBegin(GL_POINTS);
2749                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, em);
2750                 bglEnd();
2751         }
2752         else {
2753                 glLineWidth(3.0);
2754                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, em);
2755                 glLineWidth(1.0);
2756         }
2757 }
2758
2759 /* Second section of routines: Combine first sets to form fancy
2760  * drawing routines (for example rendering twice to get overlays).
2761  *
2762  * Also includes routines that are basic drawing but are too
2763  * specialized to be split out (like drawing creases or measurements).
2764  */
2765
2766 /* EditMesh drawing routines*/
2767
2768 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, 
2769                                 BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act,
2770                                                                 RegionView3D *rv3d)
2771 {
2772         ToolSettings *ts = scene->toolsettings;
2773         int sel;
2774
2775         if (v3d->zbuf) glDepthMask(0);      // disable write in zbuffer, zbuf select
2776
2777         for (sel = 0; sel < 2; sel++) {
2778                 unsigned char col[4], fcol[4];
2779                 int pass;
2780
2781                 UI_GetThemeColor3ubv(sel ? TH_VERTEX_SELECT : TH_VERTEX, col);
2782                 UI_GetThemeColor3ubv(sel ? TH_FACE_DOT : TH_WIRE, fcol);
2783
2784                 for (pass = 0; pass < 2; pass++) {
2785                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2786                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2787
2788                         if (pass == 0) {
2789                                 if (v3d->zbuf && !(v3d->flag & V3D_ZBUF_SELECT)) {
2790                                         glDisable(GL_DEPTH_TEST);
2791
2792                                         glEnable(GL_BLEND);
2793                                 }
2794                                 else {
2795                                         continue;
2796                                 }
2797
2798                                 size = (size > 2.1f ? size / 2.0f : size);
2799                                 fsize = (fsize > 2.1f ? fsize / 2.0f : fsize);
2800                                 col[3] = fcol[3] = 100;
2801                         }
2802                         else {
2803                                 col[3] = fcol[3] = 255;
2804                         }
2805
2806                         if (ts->selectmode & SCE_SELECT_VERTEX) {
2807                                 glPointSize(size);
2808                                 glColor4ubv(col);
2809                                 draw_dm_verts(em, cageDM, sel, eve_act, rv3d);
2810                         }
2811                         
2812                         if (check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2813                                 glPointSize(fsize);
2814                                 glColor4ubv(fcol);
2815                                 draw_dm_face_centers(em, cageDM, sel);
2816                         }
2817                         
2818                         if (pass == 0) {
2819                                 glDisable(GL_BLEND);
2820                                 glEnable(GL_DEPTH_TEST);
2821                         }
2822                 }
2823         }
2824
2825         if (v3d->zbuf) glDepthMask(1);
2826         glPointSize(1.0);
2827 }
2828
2829 static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d,
2830                                 Mesh *me, DerivedMesh *cageDM, short sel_only,
2831                                 BMEdge *eed_act)
2832 {
2833         ToolSettings *ts = scene->toolsettings;
2834         int pass;
2835         unsigned char wireCol[4], selCol[4], actCol[4];
2836
2837         /* since this function does transparant... */
2838         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2839         UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2840         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2841         
2842         /* when sel only is used, don't render wire, only selected, this is used for
2843          * textured draw mode when the 'edges' option is disabled */
2844         if (sel_only)
2845                 wireCol[3] = 0;
2846
2847         for (pass = 0; pass < 2; pass++) {
2848                 /* show wires in transparant when no zbuf clipping for select */
2849                 if (pass == 0) {
2850                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT) == 0) {
2851                                 glEnable(GL_BLEND);
2852                                 glDisable(GL_DEPTH_TEST);
2853                                 selCol[3] = 85;
2854                                 if (!sel_only) wireCol[3] = 85;
2855                         }
2856                         else {
2857                                 continue;
2858                         }
2859                 }
2860                 else {
2861                         selCol[3] = 255;
2862                         if (!sel_only) wireCol[3] = 255;
2863                 }
2864
2865                 if (ts->selectmode == SCE_SELECT_FACE) {
2866                         draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2867                 }
2868                 else if ( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {
2869                         if (cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2870                                 glShadeModel(GL_SMOOTH);
2871                                 draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol);
2872                                 glShadeModel(GL_FLAT);
2873                         }
2874                         else {
2875                                 draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2876                         }
2877                 }
2878                 else {
2879                         if (!sel_only) {
2880                                 glColor4ubv(wireCol);
2881                                 draw_dm_edges(em, cageDM);
2882                         }
2883                 }
2884
2885                 if (pass == 0) {
2886                         glDisable(GL_BLEND);
2887                         glEnable(GL_DEPTH_TEST);
2888                 }
2889         }
2890 }       
2891
2892 static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitSettings *unit)
2893 {
2894         const short txt_flag = V3D_CACHE_TEXT_ASCII | V3D_CACHE_TEXT_LOCALCLIP;
2895         Mesh *me = ob->data;
2896         float v1[3], v2[3], v3[3], vmid[3], fvec[3];
2897         char numstr[32]; /* Stores the measurement display text here */
2898         const char *conv_float; /* Use a float conversion matching the grid size */
2899         unsigned char col[4] = {0, 0, 0, 255}; /* color of the text to draw */
2900         float area; /* area of the face */
2901         float grid = unit->system ? unit->scale_length : v3d->grid;
2902         const int do_split = unit->flag & USER_UNIT_OPT_SPLIT;
2903         const int do_global = v3d->flag & V3D_GLOBAL_STATS;
2904         const int do_moving = G.moving;
2905
2906         BMIter iter;
2907         int i;
2908
2909         /* make the precision of the pronted value proportionate to the gridsize */
2910
2911         if (grid < 0.01f) conv_float = "%.6g";
2912         else if (grid < 0.1f) conv_float = "%.5g";
2913         else if (grid < 1.0f) conv_float = "%.4g";
2914         else if (grid < 10.0f) conv_float = "%.3g";
2915         else conv_float = "%.2g";
2916         
2917         if (me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2918                 BMEdge *eed;
2919
2920                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2921
2922                 eed = BM_iter_new(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
2923                 for (; eed; eed = BM_iter_step(&iter)) {
2924                         /* draw selected edges, or edges next to selected verts while draging */
2925                         if (BM_elem_flag_test(eed, BM_ELEM_SELECT) ||
2926                             (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
2927                                            BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))))
2928                         {
2929
2930                                 copy_v3_v3(v1, eed->v1->co);
2931                                 copy_v3_v3(v2, eed->v2->co);
2932
2933                                 mid_v3_v3v3(vmid, v1, v2);
2934
2935                                 if (do_global) {
2936                                         mul_mat3_m4_v3(ob->obmat, v1);
2937                                         mul_mat3_m4_v3(ob->obmat, v2);
2938                                 }
2939
2940                                 if (unit->system) {
2941                                         bUnit_AsString(numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3,
2942                                                        unit->system, B_UNIT_LENGTH, do_split, FALSE);
2943                                 }
2944                                 else {
2945                                         sprintf(numstr, conv_float, len_v3v3(v1, v2));
2946                                 }
2947
2948                                 view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);
2949                         }
2950                 }
2951         }
2952
2953         if (me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2954                 /* would be nice to use BM_face_calc_area, but that is for 2d faces
2955                  * so instead add up tessellation triangle areas */
2956                 BMFace *f;
2957                 int n;
2958
2959 #define DRAW_EM_MEASURE_STATS_FACEAREA()                                      \
2960         if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {                               \
2961                 mul_v3_fl(vmid, 1.0f / (float)n);                                     \
2962                 if (unit->system)                                                     \
2963                         bUnit_AsString(numstr, sizeof(numstr),                            \
2964                                        (double)(area * unit->scale_length),               \
2965                                        3, unit->system, B_UNIT_LENGTH, do_split, FALSE);  \
2966                 else                                                                  \
2967                         BLI_snprintf(numstr, sizeof(numstr), conv_float, area);           \
2968                 view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);          \
2969         } (void)0
2970
2971                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2972                 
2973                 f = NULL;
2974                 area = 0.0;
2975                 zero_v3(vmid);
2976                 n = 0;
2977                 for (i = 0; i < em->tottri; i++) {
2978                         BMLoop **l = em->looptris[i];
2979                         if (f && l[0]->f != f) {
2980                                 DRAW_EM_MEASURE_STATS_FACEAREA();
2981                                 zero_v3(vmid);
2982                                 area = 0.0;
2983                                 n = 0;
2984                         }
2985
2986                         f = l[0]->f;
2987                         copy_v3_v3(v1, l[0]->v->co);
2988                         copy_v3_v3(v2, l[1]->v->co);
2989                         copy_v3_v3(v3, l[2]->v->co);
2990                         add_v3_v3(vmid, v1);
2991                         add_v3_v3(vmid, v2);
2992                         add_v3_v3(vmid, v3);
2993                         n += 3;
2994                         if (do_global) {
2995                                 mul_mat3_m4_v3(ob->obmat, v1);
2996                                 mul_mat3_m4_v3(ob->obmat, v2);
2997                                 mul_mat3_m4_v3(ob->obmat, v3);
2998                         }
2999                         area += area_tri_v3(v1, v2, v3);
3000                 }
3001
3002                 if (f) {
3003                         DRAW_EM_MEASURE_STATS_FACEAREA();
3004                 }
3005 #undef DRAW_EM_MEASURE_STATS_FACEAREA
3006         }
3007
3008         if (me->drawflag & ME_DRAWEXTRA_FACEANG) {
3009                 BMFace *efa;
3010                 int is_rad = unit->system_rotation == USER_UNIT_ROT_RADIANS;
3011
3012                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
3013
3014
3015                 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
3016                         const int is_face_sel = BM_elem_flag_test(efa, BM_ELEM_SELECT);
3017
3018                         if (is_face_sel || do_moving) {
3019                                 BMIter liter;
3020                                 BMLoop *loop;
3021                                 int is_first = TRUE;
3022
3023                                 BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) {
3024                                         if (is_face_sel || (do_moving && BM_elem_flag_test(loop->v, BM_ELEM_SELECT))) {
3025                                                 float angle;
3026
3027                                                 /* lazy init center calc */
3028                                                 if (is_first) {
3029                                                         BM_face_calc_center_bounds(efa, vmid);
3030                                                         /* Avoid triple matrix multiply every vertex for 'global' */
3031                                                         if (do_global) {
3032                                                                 copy_v3_v3(v1, loop->prev->v->co);
3033                                                                 copy_v3_v3(v2, loop->v->co);
3034                                                                 mul_mat3_m4_v3(ob->obmat, v1);
3035                                                                 mul_mat3_m4_v3(ob->obmat, v2);
3036                                                         }
3037                                                         is_first = FALSE;
3038                                                 }
3039
3040                                                 if (do_global) {
3041                                                         copy_v3_v3(v3, loop->next->v->co);
3042
3043                                                         mul_mat3_m4_v3(ob->obmat, v3);
3044
3045                                                         angle = angle_v3v3v3(v1, v2, v3);
3046                                                         copy_v3_v3(v1, v2);
3047                                                         copy_v3_v3(v2, v3);
3048                                                 }
3049                                                 else {
3050                                                         angle = angle_v3v3v3(loop->prev->v->co, loop->v->co, loop->next->v->co);
3051                                                 }
3052
3053                                                 BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
3054                                                 interp_v3_v3v3(fvec, vmid, loop->v->co, 0.8f);
3055                                                 view3d_cached_text_draw_add(fvec, numstr, 0, txt_flag, col);
3056                                         }
3057                                 }
3058                         }
3059                 }
3060         }
3061 }
3062
3063 static void draw_em_indices(BMEditMesh *em)
3064 {
3065         const short txt_flag = V3D_CACHE_TEXT_ASCII | V3D_CACHE_TEXT_LOCALCLIP;
3066         BMEdge *e;
3067         BMFace *f;
3068         BMVert *v;
3069         int i;
3070         char numstr[32];
3071         float pos[3];
3072         unsigned char col[4];
3073
3074         BMIter iter;
3075         BMesh *bm = em->bm;
3076
3077         /* For now, reuse appropriate theme colors from stats text colors */
3078         i = 0;
3079         if (em->selectmode & SCE_SELECT_VERTEX) {
3080                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
3081                 BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
3082                         if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
3083                                 sprintf(numstr, "%d", i);
3084                                 view3d_cached_text_draw_add(v->co, numstr, 0, txt_flag, col);
3085                         }
3086                         i++;
3087                 }
3088         }
3089
3090         if (em->selectmode & SCE_SELECT_EDGE) {
3091                 i = 0;
3092                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
3093                 BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
3094                         if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
3095                                 sprintf(numstr, "%d", i);
3096                                 mid_v3_v3v3(pos, e->v1->co, e->v2->co);
3097                                 view3d_cached_text_draw_add(pos, numstr, 0, txt_flag, col);
3098                         }
3099                         i++;
3100                 }
3101         }
3102
3103         if (em->selectmode & SCE_SELECT_FACE) {
3104                 i = 0;
3105                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
3106                 BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
3107                         if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
3108                                 BM_face_calc_center_mean(f, pos);
3109                                 sprintf(numstr, "%d", i);
3110                                 view3d_cached_text_draw_add(pos, numstr, 0, txt_flag, col);
3111                         }
3112                         i++;
3113                 }
3114         }
3115 }
3116
3117 static DMDrawOption draw_em_fancy__setFaceOpts(void *userData, int index)
3118 {
3119         BMFace *efa = EDBM_face_at_index(userData, index);
3120
3121         if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
3122                 GPU_enable_material(efa->mat_nr + 1, NULL);
3123                 return DM_DRAW_OPTION_NORMAL;
3124         }
3125         else
3126                 return DM_DRAW_OPTION_SKIP;
3127 }
3128
3129 static DMDrawOption draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
3130 {
3131         BMFace *efa = EDBM_face_at_index(userData, index);
3132
3133         if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
3134                 return DM_DRAW_OPTION_SKIP;
3135         else
3136                 return DM_DRAW_OPTION_NORMAL;
3137 }
3138
3139 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
3140                           Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
3141
3142 {
3143         Mesh *me = ob->data;
3144         BMFace *efa_act = BM_active_face_get(em->bm, FALSE); /* annoying but active faces is stored differently */
3145         BMEdge *eed_act = NULL;
3146         BMVert *eve_act = NULL;
3147         
3148         if (em->bm->selected.last) {
3149                 BMEditSelection *ese = em->bm->selected.last;
3150                 /* face is handeled above */
3151 #if 0
3152                 if (ese->type == BM_FACE) {
3153                         efa_act = (BMFace