style cleanup
[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, int dt, int flag)
1193 {
1194         Object *ob = base->object;
1195         const float pixsize = ED_view3d_pixel_size(rv3d, ob->obmat[3]);
1196         Lamp *la = ob->data;
1197         float vec[3], lvec[3], vvec[3], circrad, x, y, z;
1198         float lampsize;
1199         float imat[4][4], curcol[4];
1200         unsigned char col[4];
1201         /* cone can't be drawn for duplicated lamps, because duplilist would be freed to */
1202         /* the moment of view3d_draw_transp() call */
1203         const short is_view = (rv3d->persp == RV3D_CAMOB && v3d->camera == base->object);
1204         const short drawcone = ((dt > OB_WIRE) &&
1205                                 !(G.f & G_PICKSEL) &&
1206                                 (la->type == LA_SPOT) &&
1207                                 (la->mode & LA_SHOW_CONE) &&
1208                                 !(base->flag & OB_FROMDUPLI) &&
1209                                 !is_view);
1210
1211         if (drawcone && !v3d->transp) {
1212                 /* in this case we need to draw delayed */
1213                 add_view3d_after(&v3d->afterdraw_transp, base, flag);
1214                 return;
1215         }
1216         
1217         /* we first draw only the screen aligned & fixed scale stuff */
1218         glPushMatrix();
1219         glLoadMatrixf(rv3d->viewmat);
1220
1221         /* lets calculate the scale: */
1222         lampsize = pixsize * ((float)U.obcenter_dia * 0.5f);
1223
1224         /* and view aligned matrix: */
1225         copy_m4_m4(imat, rv3d->viewinv);
1226         normalize_v3(imat[0]);
1227         normalize_v3(imat[1]);
1228
1229         /* lamp center */
1230         copy_v3_v3(vec, ob->obmat[3]);
1231         
1232         /* for AA effects */
1233         glGetFloatv(GL_CURRENT_COLOR, curcol);
1234         curcol[3] = 0.6;
1235         glColor4fv(curcol);
1236         
1237         if (lampsize > 0.0f) {
1238
1239                 if (ob->id.us > 1) {
1240                         if (ob == OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
1241                         else glColor4ub(0x77, 0xCC, 0xCC, 155);
1242                 }
1243                 
1244                 /* Inner Circle */
1245                 glEnable(GL_BLEND);
1246                 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
1247                 glDisable(GL_BLEND);
1248                 drawcircball(GL_POLYGON, vec, lampsize, imat);
1249                 
1250                 /* restore */
1251                 if (ob->id.us > 1)
1252                         glColor4fv(curcol);
1253
1254                 /* Outer circle */
1255                 circrad = 3.0f * lampsize;
1256                 setlinestyle(3);
1257
1258                 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
1259
1260                 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
1261                 if (la->type != LA_HEMI) {
1262                         if ((la->mode & LA_SHAD_RAY) || ((la->mode & LA_SHAD_BUF) && (la->type == LA_SPOT))) {
1263                                 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f * pixsize, imat);
1264                         }
1265                 }
1266         }
1267         else {
1268                 setlinestyle(3);
1269                 circrad = 0.0f;
1270         }
1271         
1272         /* draw the pretty sun rays */
1273         if (la->type == LA_SUN) {
1274                 float v1[3], v2[3], mat[3][3];
1275                 short axis;
1276                 
1277                 /* setup a 45 degree rotation matrix */
1278                 vec_rot_to_mat3(mat, imat[2], (float)M_PI / 4.0f);
1279                 
1280                 /* vectors */
1281                 mul_v3_v3fl(v1, imat[0], circrad * 1.2f);
1282                 mul_v3_v3fl(v2, imat[0], circrad * 2.5f);
1283                 
1284                 /* center */
1285                 glTranslatef(vec[0], vec[1], vec[2]);
1286                 
1287                 setlinestyle(3);
1288                 
1289                 glBegin(GL_LINES);
1290                 for (axis = 0; axis < 8; axis++) {
1291                         glVertex3fv(v1);
1292                         glVertex3fv(v2);
1293                         mul_m3_v3(mat, v1);
1294                         mul_m3_v3(mat, v2);
1295                 }
1296                 glEnd();
1297                 
1298                 glTranslatef(-vec[0], -vec[1], -vec[2]);
1299
1300         }
1301         
1302         if (la->type == LA_LOCAL) {
1303                 if (la->mode & LA_SPHERE) {
1304                         drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
1305                 }
1306         }
1307         
1308         glPopMatrix();  /* back in object space */
1309         zero_v3(vec);
1310         
1311         if (is_view) {
1312                 /* skip drawing extra info */
1313         }
1314         else if ((la->type == LA_SPOT) || (la->type == LA_YF_PHOTON)) {
1315                 lvec[0] = lvec[1] = 0.0;
1316                 lvec[2] = 1.0;
1317                 x = rv3d->persmat[0][2];
1318                 y = rv3d->persmat[1][2];
1319                 z = rv3d->persmat[2][2];
1320                 vvec[0] = x * ob->obmat[0][0] + y * ob->obmat[0][1] + z * ob->obmat[0][2];
1321                 vvec[1] = x * ob->obmat[1][0] + y * ob->obmat[1][1] + z * ob->obmat[1][2];
1322                 vvec[2] = x * ob->obmat[2][0] + y * ob->obmat[2][1] + z * ob->obmat[2][2];
1323
1324                 y = cosf(la->spotsize * (float)(M_PI / 360.0));
1325                 spotvolume(lvec, vvec, y);
1326                 x = -la->dist;
1327                 mul_v3_fl(lvec, x);
1328                 mul_v3_fl(vvec, x);
1329
1330                 /* draw the angled sides of the cone */
1331                 glBegin(GL_LINE_STRIP);
1332                 glVertex3fv(vvec);
1333                 glVertex3fv(vec);
1334                 glVertex3fv(lvec);
1335                 glEnd();
1336                 
1337                 z = x * sqrtf(1.0f - y * y);
1338                 x *= y;
1339
1340                 /* draw the circle/square at the end of the cone */
1341                 glTranslatef(0.0, 0.0,  x);
1342                 if (la->mode & LA_SQUARE) {
1343                         float tvec[3];
1344                         float z_abs = fabs(z);
1345
1346                         tvec[0] = tvec[1] = z_abs;
1347                         tvec[2] = 0.0;
1348
1349                         glBegin(GL_LINE_LOOP);
1350                         glVertex3fv(tvec);
1351                         tvec[1] = -z_abs; /* neg */
1352                         glVertex3fv(tvec);
1353                         tvec[0] = -z_abs; /* neg */
1354                         glVertex3fv(tvec);
1355                         tvec[1] = z_abs; /* pos */
1356                         glVertex3fv(tvec);
1357                         glEnd();
1358                 }
1359                 else circ(0.0, 0.0, fabsf(z));
1360                 
1361                 /* draw the circle/square representing spotbl */
1362                 if (la->type == LA_SPOT) {
1363                         float spotblcirc = fabs(z) * (1 - pow(la->spotblend, 2));
1364                         /* hide line if it is zero size or overlaps with outer border,
1365                          * previously it adjusted to always to show it but that seems
1366                          * confusing because it doesn't show the actual blend size */
1367                         if (spotblcirc != 0 && spotblcirc != fabsf(z))
1368                                 circ(0.0, 0.0, spotblcirc);
1369                 }
1370
1371                 if (drawcone)
1372                         draw_transp_spot_volume(la, x, z);
1373
1374                 /* draw clip start, useful for wide cones where its not obvious where the start is */
1375                 glTranslatef(0.0, 0.0, -x);  /* reverse translation above */
1376                 if (la->type == LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
1377                         float lvec_clip[3];
1378                         float vvec_clip[3];
1379                         float clipsta_fac = la->clipsta / -x;
1380
1381                         interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac);
1382                         interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac);
1383
1384                         glBegin(GL_LINE_STRIP);
1385                         glVertex3fv(lvec_clip);
1386                         glVertex3fv(vvec_clip);
1387                         glEnd();
1388                 }
1389         }
1390         else if (ELEM(la->type, LA_HEMI, LA_SUN)) {
1391                 
1392                 /* draw the line from the circle along the dist */
1393                 glBegin(GL_LINE_STRIP);
1394                 vec[2] = -circrad;
1395                 glVertex3fv(vec);
1396                 vec[2] = -la->dist;
1397                 glVertex3fv(vec);
1398                 glEnd();
1399                 
1400                 if (la->type == LA_HEMI) {
1401                         /* draw the hemisphere curves */
1402                         short axis, steps, dir;
1403                         float outdist, zdist, mul;
1404                         zero_v3(vec);
1405                         outdist = 0.14; mul = 1.4; dir = 1;
1406                         
1407                         setlinestyle(4);
1408                         /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
1409                         for (axis = 0; axis < 4; axis++) {
1410                                 float v[3] = {0.0, 0.0, 0.0};
1411                                 zdist = 0.02;
1412                                 
1413                                 glBegin(GL_LINE_STRIP);
1414                                 
1415                                 for (steps = 0; steps < 6; steps++) {
1416                                         if (axis == 0 || axis == 1) {       /* x axis up, x axis down */
1417                                                 /* make the arcs start at the edge of the energy circle */
1418                                                 if (steps == 0) v[0] = dir * circrad;
1419                                                 else v[0] = v[0] + dir * (steps * outdist);
1420                                         }
1421                                         else if (axis == 2 || axis == 3) {      /* y axis up, y axis down */
1422                                                 /* make the arcs start at the edge of the energy circle */
1423                                                 v[1] = (steps == 0) ? (dir * circrad) : (v[1] + dir * (steps * outdist));
1424                                         }
1425
1426                                         v[2] = v[2] - steps * zdist;
1427                                         
1428                                         glVertex3fv(v);
1429                                         
1430                                         zdist = zdist * mul;
1431                                 }
1432                                 
1433                                 glEnd();
1434                                 /* flip the direction */
1435                                 dir = -dir;
1436                         }
1437                 }
1438         }
1439         else if (la->type == LA_AREA) {
1440                 setlinestyle(3);
1441                 if (la->area_shape == LA_AREA_SQUARE)
1442                         fdrawbox(-la->area_size * 0.5f, -la->area_size * 0.5f, la->area_size * 0.5f, la->area_size * 0.5f);
1443                 else if (la->area_shape == LA_AREA_RECT)
1444                         fdrawbox(-la->area_size * 0.5f, -la->area_sizey * 0.5f, la->area_size * 0.5f, la->area_sizey * 0.5f);
1445
1446                 glBegin(GL_LINE_STRIP);
1447                 glVertex3f(0.0, 0.0, -circrad);
1448                 glVertex3f(0.0, 0.0, -la->dist);
1449                 glEnd();
1450         }
1451         
1452         /* and back to viewspace */
1453         glLoadMatrixf(rv3d->viewmat);
1454         copy_v3_v3(vec, ob->obmat[3]);
1455
1456         setlinestyle(0);
1457         
1458         if ((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == FALSE)) {
1459                 drawshadbuflimits(la, ob->obmat);
1460         }
1461         
1462         UI_GetThemeColor4ubv(TH_LAMP, col);
1463         glColor4ubv(col);
1464
1465         glEnable(GL_BLEND);
1466         
1467         if (vec[2] > 0) vec[2] -= circrad;
1468         else vec[2] += circrad;
1469         
1470         glBegin(GL_LINE_STRIP);
1471         glVertex3fv(vec);
1472         vec[2] = 0;
1473         glVertex3fv(vec);
1474         glEnd();
1475         
1476         glPointSize(2.0);
1477         glBegin(GL_POINTS);
1478         glVertex3fv(vec);
1479         glEnd();
1480         glPointSize(1.0);
1481         
1482         glDisable(GL_BLEND);
1483         
1484         /* restore for drawing extra stuff */
1485         glColor3fv(curcol);
1486
1487 }
1488
1489 static void draw_limit_line(float sta, float end, unsigned int col)
1490 {
1491         glBegin(GL_LINES);
1492         glVertex3f(0.0, 0.0, -sta);
1493         glVertex3f(0.0, 0.0, -end);
1494         glEnd();
1495
1496         glPointSize(3.0);
1497         glBegin(GL_POINTS);
1498         cpack(col);
1499         glVertex3f(0.0, 0.0, -sta);
1500         glVertex3f(0.0, 0.0, -end);
1501         glEnd();
1502         glPointSize(1.0);
1503 }               
1504
1505
1506 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1507 /* qdn: now also enabled for Blender to set focus point for defocus composite node */
1508 static void draw_focus_cross(float dist, float size)
1509 {
1510         glBegin(GL_LINES);
1511         glVertex3f(-size, 0.f, -dist);
1512         glVertex3f(size, 0.f, -dist);
1513         glVertex3f(0.f, -size, -dist);
1514         glVertex3f(0.f, size, -dist);
1515         glEnd();
1516 }
1517
1518 #ifdef VIEW3D_CAMERA_BORDER_HACK
1519 float view3d_camera_border_hack_col[4];
1520 short view3d_camera_border_hack_test = FALSE;
1521 #endif
1522
1523 /* ****************** draw clip data *************** */
1524
1525 static void draw_bundle_sphere(void)
1526 {
1527         static GLuint displist = 0;
1528
1529         if (displist == 0) {
1530                 GLUquadricObj *qobj;
1531
1532                 displist = glGenLists(1);
1533                 glNewList(displist, GL_COMPILE);
1534
1535                 qobj = gluNewQuadric();
1536                 gluQuadricDrawStyle(qobj, GLU_FILL);
1537                 glShadeModel(GL_SMOOTH);
1538                 gluSphere(qobj, 0.05, 8, 8);
1539                 glShadeModel(GL_FLAT);
1540                 gluDeleteQuadric(qobj);
1541
1542                 glEndList();
1543         }
1544
1545         glCallList(displist);
1546 }
1547
1548 static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D *v3d,
1549                                                 MovieClip *clip, MovieTrackingObject *tracking_object, int flag,
1550                                                 int *global_track_index, int draw_selected)
1551 {
1552         MovieTracking *tracking = &clip->tracking;
1553         MovieTrackingTrack *track;
1554         float mat[4][4], imat[4][4];
1555         unsigned char col[4], scol[4];
1556         int tracknr = *global_track_index;
1557         ListBase *tracksbase = BKE_tracking_object_tracks(tracking, tracking_object);
1558
1559         UI_GetThemeColor4ubv(TH_TEXT, col);
1560         UI_GetThemeColor4ubv(TH_SELECT, scol);
1561
1562         BKE_get_tracking_mat(scene, base->object, mat);
1563
1564         glPushMatrix();
1565
1566         if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
1567                 /* current ogl matrix is translated in camera space, bundles should
1568                  * be rendered in world space, so camera matrix should be "removed"
1569                  * from current ogl matrix */
1570                 invert_m4_m4(imat, base->object->obmat);
1571
1572                 glMultMatrixf(imat);
1573                 glMultMatrixf(mat);
1574         }
1575         else {
1576                 float obmat[4][4];
1577
1578                 BKE_tracking_get_interpolated_camera(tracking, tracking_object, scene->r.cfra, obmat);
1579
1580                 invert_m4_m4(imat, obmat);
1581                 glMultMatrixf(imat);
1582         }
1583
1584         for (track = tracksbase->first; track; track = track->next) {
1585                 int selected = TRACK_SELECTED(track);
1586
1587                 if (draw_selected && !selected)
1588                         continue;
1589
1590                 if ((track->flag & TRACK_HAS_BUNDLE) == 0)
1591                         continue;
1592
1593                 if (flag & DRAW_PICKING)
1594                         glLoadName(base->selcol + (tracknr << 16));
1595
1596                 glPushMatrix();
1597                 glTranslatef(track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
1598                 glScalef(v3d->bundle_size / 0.05f, v3d->bundle_size / 0.05f, v3d->bundle_size / 0.05f);
1599
1600                 if (v3d->drawtype == OB_WIRE) {
1601                         glDisable(GL_LIGHTING);
1602
1603                         if (selected) {
1604                                 if (base == BASACT) UI_ThemeColor(TH_ACTIVE);
1605                                 else UI_ThemeColor(TH_SELECT);
1606                         }
1607                         else {
1608                                 if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1609                                 else UI_ThemeColor(TH_WIRE);
1610                         }
1611
1612                         drawaxes(0.05f, v3d->bundle_drawtype);
1613
1614                         glEnable(GL_LIGHTING);
1615                 }
1616                 else if (v3d->drawtype > OB_WIRE) {
1617                         if (v3d->bundle_drawtype == OB_EMPTY_SPHERE) {
1618                                 /* selection outline */
1619                                 if (selected) {
1620                                         if (base == BASACT) UI_ThemeColor(TH_ACTIVE);
1621                                         else UI_ThemeColor(TH_SELECT);
1622
1623                                         glLineWidth(2.f);
1624                                         glDisable(GL_LIGHTING);
1625                                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1626
1627                                         draw_bundle_sphere();
1628
1629                                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1630                                         glEnable(GL_LIGHTING);
1631                                         glLineWidth(1.f);
1632                                 }
1633
1634                                 if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1635                                 else UI_ThemeColor(TH_BUNDLE_SOLID);
1636
1637                                 draw_bundle_sphere();
1638                         }
1639                         else {
1640                                 glDisable(GL_LIGHTING);
1641
1642                                 if (selected) {
1643                                         if (base == BASACT) UI_ThemeColor(TH_ACTIVE);
1644                                         else UI_ThemeColor(TH_SELECT);
1645                                 }
1646                                 else {
1647                                         if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1648                                         else UI_ThemeColor(TH_WIRE);
1649                                 }
1650
1651                                 drawaxes(0.05f, v3d->bundle_drawtype);
1652
1653                                 glEnable(GL_LIGHTING);
1654                         }
1655                 }
1656
1657                 glPopMatrix();
1658
1659                 if ((flag & DRAW_PICKING) == 0 && (v3d->flag2 & V3D_SHOW_BUNDLENAME)) {
1660                         float pos[3];
1661                         unsigned char tcol[4];
1662
1663                         if (selected) memcpy(tcol, scol, sizeof(tcol));
1664                         else memcpy(tcol, col, sizeof(tcol));
1665
1666                         mul_v3_m4v3(pos, mat, track->bundle_pos);
1667                         view3d_cached_text_draw_add(pos, track->name, 10, V3D_CACHE_TEXT_GLOBALSPACE, tcol);
1668                 }
1669
1670                 tracknr++;
1671         }
1672
1673         if ((flag & DRAW_PICKING) == 0) {
1674                 if ((v3d->flag2 & V3D_SHOW_CAMERAPATH) && (tracking_object->flag & TRACKING_OBJECT_CAMERA)) {
1675                         MovieTrackingReconstruction *reconstruction;
1676                         reconstruction = BKE_tracking_object_reconstruction(tracking, tracking_object);
1677
1678                         if (reconstruction->camnr) {
1679                                 MovieReconstructedCamera *camera = reconstruction->cameras;
1680                                 int a = 0;
1681
1682                                 glDisable(GL_LIGHTING);
1683                                 UI_ThemeColor(TH_CAMERA_PATH);
1684                                 glLineWidth(2.0f);
1685
1686                                 glBegin(GL_LINE_STRIP);
1687                                 for (a = 0; a < reconstruction->camnr; a++, camera++) {
1688                                         glVertex3fv(camera->mat[3]);
1689                                 }
1690                                 glEnd();
1691
1692                                 glLineWidth(1.0f);
1693                                 glEnable(GL_LIGHTING);
1694                         }
1695                 }
1696         }
1697
1698         glPopMatrix();
1699
1700         *global_track_index = tracknr;
1701 }
1702
1703 static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, MovieClip *clip,
1704                                          int flag, int draw_selected)
1705 {
1706         MovieTracking *tracking = &clip->tracking;
1707         MovieTrackingObject *tracking_object;
1708         float curcol[4];
1709         int global_track_index = 1;
1710
1711         if ((v3d->flag2 & V3D_SHOW_RECONSTRUCTION) == 0)
1712                 return;
1713
1714         if (v3d->flag2 & V3D_RENDER_OVERRIDE)
1715                 return;
1716
1717         glGetFloatv(GL_CURRENT_COLOR, curcol);
1718
1719         glEnable(GL_LIGHTING);
1720         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1721         glEnable(GL_COLOR_MATERIAL);
1722         glShadeModel(GL_SMOOTH);
1723
1724         tracking_object = tracking->objects.first;
1725         while (tracking_object) {
1726                 draw_viewport_object_reconstruction(scene, base, v3d, clip, tracking_object,
1727                                                     flag, &global_track_index, draw_selected);
1728
1729                 tracking_object = tracking_object->next;
1730         }
1731
1732         /* restore */
1733         glShadeModel(GL_FLAT);
1734         glDisable(GL_COLOR_MATERIAL);
1735         glDisable(GL_LIGHTING);
1736
1737         glColor4fv(curcol);
1738
1739         if (flag & DRAW_PICKING)
1740                 glLoadName(base->selcol);
1741 }
1742
1743 /* flag similar to draw_object() */
1744 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int flag)
1745 {
1746         /* a standing up pyramid with (0,0,0) as top */
1747         Camera *cam;
1748         Object *ob = base->object;
1749         float tvec[3];
1750         float vec[4][3], asp[2], shift[2], scale[3];
1751         int i;
1752         float drawsize;
1753         const short is_view = (rv3d->persp == RV3D_CAMOB && ob == v3d->camera);
1754         MovieClip *clip = BKE_object_movieclip_get(scene, base->object, 0);
1755
1756         /* draw data for movie clip set as active for scene */
1757         if (clip) {
1758                 draw_viewport_reconstruction(scene, base, v3d, clip, flag, FALSE);
1759                 draw_viewport_reconstruction(scene, base, v3d, clip, flag, TRUE);
1760         }
1761
1762 #ifdef VIEW3D_CAMERA_BORDER_HACK
1763         if (is_view && !(G.f & G_PICKSEL)) {
1764                 glGetFloatv(GL_CURRENT_COLOR, view3d_camera_border_hack_col);
1765                 view3d_camera_border_hack_test = TRUE;
1766                 return;
1767         }
1768 #endif
1769
1770         cam = ob->data;
1771
1772         scale[0] = 1.0f / len_v3(ob->obmat[0]);
1773         scale[1] = 1.0f / len_v3(ob->obmat[1]);
1774         scale[2] = 1.0f / len_v3(ob->obmat[2]);
1775
1776         BKE_camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale,
1777                                  asp, shift, &drawsize, vec);
1778
1779         glDisable(GL_LIGHTING);
1780         glDisable(GL_CULL_FACE);
1781
1782         /* camera frame */
1783         glBegin(GL_LINE_LOOP);
1784         glVertex3fv(vec[0]);
1785         glVertex3fv(vec[1]);
1786         glVertex3fv(vec[2]);
1787         glVertex3fv(vec[3]);
1788         glEnd();
1789
1790         if (is_view)
1791                 return;
1792
1793         zero_v3(tvec);
1794
1795         /* center point to camera frame */
1796         glBegin(GL_LINE_STRIP);
1797         glVertex3fv(vec[1]);
1798         glVertex3fv(tvec);
1799         glVertex3fv(vec[0]);
1800         glVertex3fv(vec[3]);
1801         glVertex3fv(tvec);
1802         glVertex3fv(vec[2]);
1803         glEnd();
1804
1805
1806         /* arrow on top */
1807         tvec[2] = vec[1][2]; /* copy the depth */
1808
1809
1810         /* draw an outline arrow for inactive cameras and filled
1811          * for active cameras. We actually draw both outline+filled
1812          * for active cameras so the wire can be seen side-on */
1813         for (i = 0; i < 2; i++) {
1814                 if (i == 0) glBegin(GL_LINE_LOOP);
1815                 else if (i == 1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1816                 else break;
1817
1818                 tvec[0] = shift[0] + ((-0.7f * drawsize) * scale[0]);
1819                 tvec[1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]);
1820                 glVertex3fv(tvec); /* left */
1821                 
1822                 tvec[0] = shift[0] + ((0.7f * drawsize) * scale[0]);
1823                 glVertex3fv(tvec); /* right */
1824                 
1825                 tvec[0] = shift[0];
1826                 tvec[1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
1827                 glVertex3fv(tvec); /* top */
1828
1829                 glEnd();
1830         }
1831
1832         if (flag == 0) {
1833                 if (cam->flag & (CAM_SHOWLIMITS + CAM_SHOWMIST)) {
1834                         float nobmat[4][4];
1835                         World *wrld;
1836
1837                         /* draw in normalized object matrix space */
1838                         copy_m4_m4(nobmat, ob->obmat);
1839                         normalize_m4(nobmat);
1840
1841                         glPushMatrix();
1842                         glLoadMatrixf(rv3d->viewmat);
1843                         glMultMatrixf(nobmat);
1844
1845                         if (cam->flag & CAM_SHOWLIMITS) {
1846                                 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1847                                 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composite node */
1848                                 draw_focus_cross(BKE_camera_object_dof_distance(ob), cam->drawsize);
1849                         }
1850
1851                         wrld = scene->world;
1852                         if (cam->flag & CAM_SHOWMIST)
1853                                 if (wrld) draw_limit_line(wrld->miststa, wrld->miststa + wrld->mistdist, 0xFFFFFF);
1854
1855                         glPopMatrix();
1856                 }
1857         }
1858 }
1859
1860 /* flag similar to draw_object() */
1861 static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d),
1862                         Object *UNUSED(ob), int UNUSED(flag))
1863 {
1864         //Speaker *spk = ob->data;
1865
1866         float vec[3];
1867         int i, j;
1868
1869         glEnable(GL_BLEND);
1870
1871         for (j = 0; j < 3; j++) {
1872                 vec[2] = 0.25f * j - 0.125f;
1873
1874                 glBegin(GL_LINE_LOOP);
1875                 for (i = 0; i < 16; i++) {
1876                         vec[0] = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1877                         vec[1] = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1878                         glVertex3fv(vec);
1879                 }
1880                 glEnd();
1881         }
1882
1883         for (j = 0; j < 4; j++) {
1884                 vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f;
1885                 vec[1] = ((j % 2) * (j - 2)) * 0.5f;
1886                 glBegin(GL_LINE_STRIP);
1887                 for (i = 0; i < 3; i++) {
1888                         if (i == 1) {
1889                                 vec[0] *= 0.5f;
1890                                 vec[1] *= 0.5f;
1891                         }
1892
1893                         vec[2] = 0.25f * i - 0.125f;
1894                         glVertex3fv(vec);
1895                 }
1896                 glEnd();
1897         }
1898
1899         glDisable(GL_BLEND);
1900 }
1901
1902 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1903 {
1904         BPoint *bp = lt->def;
1905         float *co = dl ? dl->verts : NULL;
1906         int u, v, w;
1907
1908         UI_ThemeColor(sel ? TH_VERTEX_SELECT : TH_VERTEX);
1909         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1910         bglBegin(GL_POINTS);
1911
1912         for (w = 0; w < lt->pntsw; w++) {
1913                 int wxt = (w == 0 || w == lt->pntsw - 1);
1914                 for (v = 0; v < lt->pntsv; v++) {
1915                         int vxt = (v == 0 || v == lt->pntsv - 1);
1916                         for (u = 0; u < lt->pntsu; u++, bp++, co += 3) {
1917                                 int uxt = (u == 0 || u == lt->pntsu - 1);
1918                                 if (!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1919                                         if (bp->hide == 0) {
1920                                                 if ((bp->f1 & SELECT) == sel) {
1921                                                         bglVertex3fv(dl ? co : bp->vec);
1922                                                 }
1923                                         }
1924                                 }
1925                         }
1926                 }
1927         }
1928         
1929         glPointSize(1.0);
1930         bglEnd();
1931 }
1932
1933 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1934 {
1935         Object *obedit = vc->obedit;
1936         Lattice *lt = obedit->data;
1937         BPoint *bp = lt->editlatt->latt->def;
1938         DispList *dl = BKE_displist_find(&obedit->disp, DL_VERTS);
1939         float *co = dl ? dl->verts : NULL;
1940         int i, N = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
1941         short s[2] = {IS_CLIPPED, 0};
1942
1943         ED_view3d_clipping_local(vc->rv3d, obedit->obmat); /* for local clipping lookups */
1944
1945         for (i = 0; i < N; i++, bp++, co += 3) {
1946                 if (bp->hide == 0) {
1947                         view3d_project_short_clip(vc->ar, dl ? co : bp->vec, s, TRUE);
1948                         if (s[0] != IS_CLIPPED)
1949                                 func(userData, bp, s[0], s[1]);
1950                 }
1951         }
1952 }
1953
1954 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1955 {
1956         int index = ((w * lt->pntsv + v) * lt->pntsu) + u;
1957
1958         if (use_wcol) {
1959                 float col[3];
1960                 MDeformWeight *mdw = defvert_find_index(lt->dvert + index, use_wcol - 1);
1961                 
1962                 weight_to_rgb(col, mdw ? mdw->weight : 0.0f);
1963                 glColor3fv(col);
1964
1965         }
1966         
1967         if (dl) {
1968                 glVertex3fv(&dl->verts[index * 3]);
1969         }
1970         else {
1971                 glVertex3fv(lt->def[index].vec);
1972         }
1973 }
1974
1975 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1976 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1977 {
1978         Lattice *lt = ob->data;
1979         DispList *dl;
1980         int u, v, w;
1981         int use_wcol = FALSE, is_edit = (lt->editlatt != NULL);
1982
1983         /* now we default make displist, this will modifiers work for non animated case */
1984         if (ob->disp.first == NULL)
1985                 BKE_lattice_modifiers_calc(scene, ob);
1986         dl = BKE_displist_find(&ob->disp, DL_VERTS);
1987         
1988         if (is_edit) {
1989                 lt = lt->editlatt->latt;
1990
1991                 cpack(0x004000);
1992                 
1993                 if (ob->defbase.first && lt->dvert) {
1994                         use_wcol = ob->actdef;
1995                         glShadeModel(GL_SMOOTH);
1996                 }
1997         }
1998         
1999         glBegin(GL_LINES);
2000         for (w = 0; w < lt->pntsw; w++) {
2001                 int wxt = (w == 0 || w == lt->pntsw - 1);
2002                 for (v = 0; v < lt->pntsv; v++) {
2003                         int vxt = (v == 0 || v == lt->pntsv - 1);
2004                         for (u = 0; u < lt->pntsu; u++) {
2005                                 int uxt = (u == 0 || u == lt->pntsu - 1);
2006
2007                                 if (w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
2008                                         drawlattice__point(lt, dl, u, v, w - 1, use_wcol);
2009                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
2010                                 }
2011                                 if (v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
2012                                         drawlattice__point(lt, dl, u, v - 1, w, use_wcol);
2013                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
2014                                 }
2015                                 if (u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
2016                                         drawlattice__point(lt, dl, u - 1, v, w, use_wcol);
2017                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
2018                                 }
2019                         }
2020                 }
2021         }
2022         glEnd();
2023         
2024         /* restoration for weight colors */
2025         if (use_wcol)
2026                 glShadeModel(GL_FLAT);
2027
2028         if (is_edit) {
2029                 if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
2030                 
2031                 lattice_draw_verts(lt, dl, 0);
2032                 lattice_draw_verts(lt, dl, 1);
2033                 
2034                 if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
2035         }
2036 }
2037
2038 /* ***************** ******************** */
2039
2040 /* Note! - foreach funcs should be called while drawing or directly after
2041  * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
2042  * but would not give correct results with dupli's for eg. which don't
2043  * use the object matrix in the usual way */
2044 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, const float co[3],
2045                                             const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2046 {
2047         foreachScreenVert_userData *data = userData;
2048         BMVert *eve = EDBM_vert_at_index(data->vc.em, index);
2049
2050         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
2051                 short s[2] = {IS_CLIPPED, 0};
2052
2053                 if (data->clipVerts != V3D_CLIP_TEST_OFF) {
2054                         view3d_project_short_clip(data->vc.ar, co, s, TRUE);
2055                 }
2056                 else {
2057                         float co2[2];
2058                         mul_v3_m4v3(co2, data->vc.obedit->obmat, co);
2059                         project_short_noclip(data->vc.ar, co2, s);
2060                 }
2061
2062                 if (s[0] != IS_CLIPPED)
2063                         data->func(data->userData, eve, s[0], s[1], index);
2064         }
2065 }
2066
2067 void mesh_foreachScreenVert(
2068         ViewContext *vc,
2069         void (*func)(void *userData, BMVert *eve, int x, int y, int index),
2070         void *userData, eV3DClipTest clipVerts)
2071 {
2072         foreachScreenVert_userData data;
2073         DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2074         
2075         data.vc = *vc;
2076         data.func = func;
2077         data.userData = userData;
2078         data.clipVerts = clipVerts;
2079
2080         if (clipVerts != V3D_CLIP_TEST_OFF)
2081                 ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat);  /* for local clipping lookups */
2082
2083         EDBM_index_arrays_init(vc->em, 1, 0, 0);
2084         dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
2085         EDBM_index_arrays_free(vc->em);
2086
2087         dm->release(dm);
2088 }
2089
2090 /*  draw callback */
2091 static void drawSelectedVertices__mapFunc(void *userData, int index, const float co[3],
2092                                           const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2093 {
2094         MVert *mv = &((MVert *)userData)[index];
2095
2096         if (!(mv->flag & ME_HIDE)) {
2097                 const char sel = mv->flag & SELECT;
2098
2099                 // TODO define selected color
2100                 if (sel) {
2101                         glColor3f(1.0f, 1.0f, 0.0f);
2102                 }
2103                 else {
2104                         glColor3f(0.0f, 0.0f, 0.0f);
2105                 }
2106
2107                 glVertex3fv(co);
2108         }
2109 }
2110
2111 static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
2112 {
2113         glBegin(GL_POINTS);
2114         dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, me->mvert);
2115         glEnd();
2116 }
2117
2118 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, const float v0co[3], const float v1co[3])
2119 {
2120         foreachScreenEdge_userData *data = userData;
2121         BMEdge *eed = EDBM_edge_at_index(data->vc.em, index);
2122
2123         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
2124                 short s[2][2];
2125
2126                 if (data->clipVerts == V3D_CLIP_TEST_RV3D_CLIPPING) {
2127                         view3d_project_short_clip(data->vc.ar, v0co, s[0], TRUE);
2128                         view3d_project_short_clip(data->vc.ar, v1co, s[1], TRUE);
2129                 }
2130                 else {
2131                         float v1_co[3], v2_co[3];
2132
2133                         mul_v3_m4v3(v1_co, data->vc.obedit->obmat, v0co);
2134                         mul_v3_m4v3(v2_co, data->vc.obedit->obmat, v1co);
2135
2136                         project_short_noclip(data->vc.ar, v1_co, s[0]);
2137                         project_short_noclip(data->vc.ar, v2_co, s[1]);
2138
2139                         if (data->clipVerts == V3D_CLIP_TEST_REGION) {
2140                                 /* make an int copy */
2141                                 int s_int[2][2] = {{s[0][0], s[0][1]},
2142                                                    {s[1][0], s[1][1]}};
2143                                 if (!BLI_segment_in_rcti(&data->win_rect, s_int[0], s_int[1])) {
2144                                         return;
2145                                 }
2146                         }
2147                 }
2148
2149                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
2150         }
2151 }
2152
2153 void mesh_foreachScreenEdge(
2154         ViewContext *vc,
2155         void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index),
2156         void *userData, eV3DClipTest clipVerts)
2157 {
2158         foreachScreenEdge_userData data;
2159         DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2160
2161         data.vc = *vc;
2162
2163         data.win_rect.xmin = 0;
2164         data.win_rect.ymin = 0;
2165         data.win_rect.xmax = vc->ar->winx;
2166         data.win_rect.ymax = vc->ar->winy;
2167
2168         data.func = func;
2169         data.userData = userData;
2170         data.clipVerts = clipVerts;
2171
2172         if (clipVerts != V3D_CLIP_TEST_OFF)
2173                 ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat);  /* for local clipping lookups */
2174
2175         EDBM_index_arrays_init(vc->em, 0, 1, 0);
2176         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
2177         EDBM_index_arrays_free(vc->em);
2178
2179         dm->release(dm);
2180 }
2181
2182 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3]))
2183 {
2184         foreachScreenFace_userData *data = userData;
2185         BMFace *efa = EDBM_face_at_index(data->vc.em, index);
2186
2187         if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2188                 float cent2[3];
2189                 short s[2];
2190
2191                 mul_v3_m4v3(cent2, data->vc.obedit->obmat, cent);
2192                 project_short(data->vc.ar, cent2, s);
2193
2194                 if (s[0] != IS_CLIPPED) {
2195                         data->func(data->userData, efa, s[0], s[1], index);
2196                 }
2197         }
2198 }
2199
2200 void mesh_foreachScreenFace(
2201         ViewContext *vc,
2202         void (*func)(void *userData, BMFace *efa, int x, int y, int index),
2203         void *userData)
2204 {
2205         foreachScreenFace_userData data;
2206         DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2207
2208         data.vc = *vc;
2209         data.func = func;
2210         data.userData = userData;
2211
2212         //if (clipVerts)
2213         ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2214
2215         EDBM_index_arrays_init(vc->em, 0, 0, 1);
2216         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
2217         EDBM_index_arrays_free(vc->em);
2218
2219         dm->release(dm);
2220 }
2221
2222 void nurbs_foreachScreenVert(
2223     ViewContext *vc,
2224     void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y),
2225     void *userData)
2226 {
2227         Curve *cu = vc->obedit->data;
2228         short s[2] = {IS_CLIPPED, 0};
2229         Nurb *nu;
2230         int i;
2231         ListBase *nurbs = BKE_curve_editNurbs_get(cu);
2232
2233         ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2234
2235         for (nu = nurbs->first; nu; nu = nu->next) {
2236                 if (nu->type == CU_BEZIER) {
2237                         for (i = 0; i < nu->pntsu; i++) {
2238                                 BezTriple *bezt = &nu->bezt[i];
2239
2240                                 if (bezt->hide == 0) {
2241                                         
2242                                         if (cu->drawflag & CU_HIDE_HANDLES) {
2243                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, TRUE);
2244                                                 if (s[0] != IS_CLIPPED)
2245                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
2246                                         }
2247                                         else {
2248                                                 view3d_project_short_clip(vc->ar, bezt->vec[0], s, TRUE);
2249                                                 if (s[0] != IS_CLIPPED)
2250                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
2251                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, TRUE);
2252                                                 if (s[0] != IS_CLIPPED)
2253                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
2254                                                 view3d_project_short_clip(vc->ar, bezt->vec[2], s, TRUE);
2255                                                 if (s[0] != IS_CLIPPED)
2256                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
2257                                         }
2258                                 }
2259                         }
2260                 }
2261                 else {
2262                         for (i = 0; i < nu->pntsu * nu->pntsv; i++) {
2263                                 BPoint *bp = &nu->bp[i];
2264
2265                                 if (bp->hide == 0) {
2266                                         view3d_project_short_clip(vc->ar, bp->vec, s, TRUE);
2267                                         if (s[0] != IS_CLIPPED)
2268                                                 func(userData, nu, bp, NULL, -1, s[0], s[1]);
2269                                 }
2270                         }
2271                 }
2272         }
2273 }
2274
2275 /* ************** DRAW MESH ****************** */
2276
2277 /* First section is all the "simple" draw routines, 
2278  * ones that just pass some sort of primitive to GL,
2279  * with perhaps various options to control lighting,
2280  * color, etc.
2281  *
2282  * These routines should not have user interface related
2283  * logic!!!
2284  */
2285
2286 static void calcDrawDMNormalScale(Object *ob, drawDMNormal_userData *data)
2287 {
2288         float obmat[3][3];
2289
2290         copy_m3_m4(obmat, ob->obmat);
2291
2292         data->uniform_scale = is_uniform_scaled_m3(obmat);
2293
2294         if (!data->uniform_scale) {
2295                 /* inverted matrix */
2296                 invert_m3_m3(data->imat, obmat);
2297
2298                 /* transposed inverted matrix */
2299                 copy_m3_m3(data->tmat, data->imat);
2300                 transpose_m3(data->tmat);
2301         }
2302 }
2303
2304 static void draw_dm_face_normals__mapFunc(void *userData, int index, const float cent[3], const float no[3])
2305 {
2306         drawDMNormal_userData *data = userData;
2307         BMFace *efa = EDBM_face_at_index(data->em, index);
2308         float n[3];
2309
2310         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2311                 if (!data->uniform_scale) {
2312                         mul_v3_m3v3(n, data->tmat, (float *) no);
2313                         normalize_v3(n);
2314                         mul_m3_v3(data->imat, n);
2315                 }
2316                 else {
2317                         copy_v3_v3(n, no);
2318                 }
2319
2320                 glVertex3fv(cent);
2321                 glVertex3f(cent[0] + n[0] * data->normalsize,
2322                            cent[1] + n[1] * data->normalsize,
2323                            cent[2] + n[2] * data->normalsize);
2324         }
2325 }
2326
2327 static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
2328 {
2329         drawDMNormal_userData data;
2330
2331         data.em = em;
2332         data.normalsize = scene->toolsettings->normalsize;
2333
2334         calcDrawDMNormalScale(ob, &data);
2335
2336         glBegin(GL_LINES);
2337         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, &data);
2338         glEnd();
2339 }
2340
2341 static void draw_dm_face_centers__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3]))
2342 {
2343         BMFace *efa = EDBM_face_at_index(((void **)userData)[0], index);
2344         int sel = *(((int **)userData)[1]);
2345         
2346         if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BM_elem_flag_test(efa, BM_ELEM_SELECT) == sel) {
2347                 bglVertex3fv(cent);
2348         }
2349 }
2350 static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, int sel)
2351 {
2352         void *ptrs[2] = {em, &sel};
2353
2354         bglBegin(GL_POINTS);
2355         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, ptrs);
2356         bglEnd();
2357 }
2358
2359 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])
2360 {
2361         drawDMNormal_userData *data = userData;
2362         BMVert *eve = EDBM_vert_at_index(data->em, index);
2363
2364         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
2365                 float no[3], n[3];
2366
2367                 if (no_f) {
2368                         copy_v3_v3(no, no_f);
2369                 }
2370                 else {
2371                         no[0] = no_s[0] / 32767.0f;
2372                         no[1] = no_s[1] / 32767.0f;
2373                         no[2] = no_s[2] / 32767.0f;
2374                 }
2375
2376                 if (!data->uniform_scale) {
2377                         mul_v3_m3v3(n, data->tmat, (float *) no);
2378                         normalize_v3(n);
2379                         mul_m3_v3(data->imat, n);
2380                 }
2381                 else {
2382                         copy_v3_v3(n, no);
2383                 }
2384
2385                 glVertex3fv(co);
2386                 glVertex3f(co[0] + n[0] * data->normalsize,
2387                            co[1] + n[1] * data->normalsize,
2388                            co[2] + n[2] * data->normalsize);
2389         }
2390 }
2391
2392 static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
2393 {
2394         drawDMNormal_userData data;
2395
2396         data.em = em;
2397         data.normalsize = scene->toolsettings->normalsize;
2398
2399         calcDrawDMNormalScale(ob, &data);
2400
2401         glBegin(GL_LINES);
2402         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, &data);
2403         glEnd();
2404 }
2405
2406 /* Draw verts with color set based on selection */
2407 static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3],
2408                                    const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2409 {
2410         drawDMVerts_userData *data = userData;
2411         BMVert *eve = EDBM_vert_at_index(data->em, index);
2412
2413         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->sel) {
2414                 /* skin nodes: draw a red circle around the root
2415                  * node(s) */
2416                 if (data->has_vskin) {
2417                         const MVertSkin *vs = CustomData_bmesh_get(&data->em->bm->vdata,
2418                                                                    eve->head.data,
2419                                                                    CD_MVERT_SKIN);
2420                         if (vs->flag & MVERT_SKIN_ROOT) {
2421                                 float radius = (vs->radius[0] + vs->radius[1]) * 0.5f;
2422                                 bglEnd();
2423                         
2424                                 glColor4ubv(data->th_skin_root);
2425                                 drawcircball(GL_LINES, co, radius, data->imat);
2426
2427                                 glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex);
2428                                 bglBegin(GL_POINTS);
2429                         }
2430                 }
2431
2432                 /* draw active larger - need to stop/start point drawing for this :/ */
2433                 if (eve == data->eve_act) {
2434                         glColor4ubv(data->th_editmesh_active);
2435                         
2436                         bglEnd();
2437                         
2438                         glPointSize(data->th_vertex_size);
2439                         bglBegin(GL_POINTS);
2440                         bglVertex3fv(co);
2441                         bglEnd();
2442
2443                         glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex);
2444                         glPointSize(data->th_vertex_size);
2445                         bglBegin(GL_POINTS);
2446                 }
2447                 else {
2448                         bglVertex3fv(co);
2449                 }
2450         }
2451 }
2452
2453 static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, int sel, BMVert *eve_act,
2454                                                   RegionView3D *rv3d)
2455 {
2456         drawDMVerts_userData data;
2457         data.sel = sel;
2458         data.eve_act = eve_act;
2459         data.em = em;
2460
2461         /* Cache theme values */
2462         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, data.th_editmesh_active);
2463         UI_GetThemeColor4ubv(TH_VERTEX_SELECT, data.th_vertex_select);
2464         UI_GetThemeColor4ubv(TH_VERTEX, data.th_vertex);
2465         UI_GetThemeColor4ubv(TH_SKIN_ROOT, data.th_skin_root);
2466         data.th_vertex_size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2467
2468         /* For skin root drawing */
2469         data.has_vskin = CustomData_has_layer(&em->bm->vdata, CD_MVERT_SKIN);
2470         /* view-aligned matrix */
2471         mult_m4_m4m4(data.imat, rv3d->viewmat, em->ob->obmat);
2472         invert_m4(data.imat);
2473
2474         bglBegin(GL_POINTS);
2475         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
2476         bglEnd();
2477 }
2478
2479 /* Draw edges with color set based on selection */
2480 static DMDrawOption draw_dm_edges_sel__setDrawOptions(void *userData, int index)
2481 {
2482         BMEdge *eed;
2483         //unsigned char **cols = userData, *col;
2484         drawDMEdgesSel_userData *data = userData;
2485         unsigned char *col;
2486
2487         eed = EDBM_edge_at_index(data->em, index);
2488
2489         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
2490                 if (eed == data->eed_act) {
2491                         glColor4ubv(data->actCol);
2492                 }
2493                 else {
2494                         if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
2495                                 col = data->selCol;
2496                         }
2497                         else {
2498                                 col = data->baseCol;
2499                         }
2500                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
2501                         if (col[3] == 0)
2502                                 return DM_DRAW_OPTION_SKIP;
2503                         
2504                         glColor4ubv(col);
2505                 }
2506                 return DM_DRAW_OPTION_NORMAL;
2507         }
2508         else {
2509                 return DM_DRAW_OPTION_SKIP;
2510         }
2511 }
2512 static void draw_dm_edges_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, 
2513                               unsigned char *selCol, unsigned char *actCol, BMEdge *eed_act)
2514 {
2515         drawDMEdgesSel_userData data;
2516         
2517         data.baseCol = baseCol;
2518         data.selCol = selCol;
2519         data.actCol = actCol;
2520         data.em = em;
2521         data.eed_act = eed_act;
2522         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
2523 }
2524
2525 /* Draw edges */
2526 static DMDrawOption draw_dm_edges__setDrawOptions(void *userData, int index)
2527 {
2528         if (BM_elem_flag_test(EDBM_edge_at_index(userData, index), BM_ELEM_HIDDEN))
2529                 return DM_DRAW_OPTION_SKIP;
2530         else
2531                 return DM_DRAW_OPTION_NORMAL;
2532 }
2533
2534 static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm) 
2535 {
2536         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, em);
2537 }
2538
2539 /* Draw edges with color interpolated based on selection */
2540 static DMDrawOption draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
2541 {
2542         if (BM_elem_flag_test(EDBM_edge_at_index(((void **)userData)[0], index), BM_ELEM_HIDDEN))
2543                 return DM_DRAW_OPTION_SKIP;
2544         else
2545                 return DM_DRAW_OPTION_NORMAL;
2546 }
2547 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2548 {
2549         BMEdge *eed = EDBM_edge_at_index(((void **)userData)[0], index);
2550         unsigned char **cols = userData;
2551         unsigned char *col0 = cols[(BM_elem_flag_test(eed->v1, BM_ELEM_SELECT)) ? 2 : 1];
2552         unsigned char *col1 = cols[(BM_elem_flag_test(eed->v2, BM_ELEM_SELECT)) ? 2 : 1];
2553
2554         glColor4ub(col0[0] + (col1[0] - col0[0]) * t,
2555                    col0[1] + (col1[1] - col0[1]) * t,
2556                    col0[2] + (col1[2] - col0[2]) * t,
2557                    col0[3] + (col1[3] - col0[3]) * t);
2558 }
2559
2560 static void draw_dm_edges_sel_interp(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2561 {
2562         void *cols[3] = {em, baseCol, selCol};
2563
2564         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2565 }
2566
2567 /* Draw only seam edges */
2568 static DMDrawOption draw_dm_edges_seams__setDrawOptions(void *userData, int index)
2569 {
2570         BMEdge *eed = EDBM_edge_at_index(userData, index);
2571
2572         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BM_elem_flag_test(eed, BM_ELEM_SEAM))
2573                 return DM_DRAW_OPTION_NORMAL;
2574         else
2575                 return DM_DRAW_OPTION_SKIP;
2576 }
2577
2578 static void draw_dm_edges_seams(BMEditMesh *em, DerivedMesh *dm)
2579 {
2580         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, em);
2581 }
2582
2583 /* Draw only sharp edges */
2584 static DMDrawOption draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
2585 {
2586         BMEdge *eed = EDBM_edge_at_index(userData, index);
2587
2588         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && !BM_elem_flag_test(eed, BM_ELEM_SMOOTH))
2589                 return DM_DRAW_OPTION_NORMAL;
2590         else
2591                 return DM_DRAW_OPTION_SKIP;
2592 }
2593
2594 static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm)
2595 {
2596         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, em);
2597 }
2598
2599
2600 /* Draw faces with color set based on selection
2601  * return 2 for the active face so it renders with stipple enabled */
2602 static DMDrawOption draw_dm_faces_sel__setDrawOptions(void *userData, int index)
2603 {
2604         drawDMFacesSel_userData *data = userData;
2605         BMFace *efa = EDBM_face_at_index(data->em, index);
2606         unsigned char *col;
2607         
2608         if (!efa)
2609                 return DM_DRAW_OPTION_SKIP;
2610         
2611         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2612                 if (efa == data->efa_act) {
2613                         glColor4ubv(data->cols[2]);
2614                         return DM_DRAW_OPTION_STIPPLE;
2615                 }
2616                 else {
2617                         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
2618                         if (col[3] == 0)
2619                                 return DM_DRAW_OPTION_SKIP;
2620                         glColor4ubv(col);
2621                         return DM_DRAW_OPTION_NORMAL;
2622                 }
2623         }
2624         return DM_DRAW_OPTION_SKIP;
2625 }
2626
2627 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2628 {
2629
2630         drawDMFacesSel_userData *data = userData;
2631         BMFace *efa;
2632         BMFace *next_efa;
2633
2634         unsigned char *col, *next_col;
2635
2636         if (!data->orig_index)
2637                 return 0;
2638
2639         efa = EDBM_face_at_index(data->em, data->orig_index[index]);
2640         next_efa = EDBM_face_at_index(data->em, data->orig_index[next_index]);
2641
2642         if (efa == next_efa)
2643                 return 1;
2644
2645         if (efa == data->efa_act || next_efa == data->efa_act)
2646                 return 0;
2647
2648         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
2649         next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT) ? 1 : 0];
2650
2651         if (col[3] == 0 || next_col[3] == 0)
2652                 return 0;
2653
2654         return col == next_col;
2655 }
2656
2657 /* also draws the active face */
2658 static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, 
2659                               unsigned char *selCol, unsigned char *actCol, BMFace *efa_act)
2660 {
2661         drawDMFacesSel_userData data;
2662         data.dm = dm;
2663         data.cols[0] = baseCol;
2664         data.em = em;
2665         data.cols[1] = selCol;
2666         data.cols[2] = actCol;
2667         data.efa_act = efa_act;
2668         data.orig_index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
2669
2670         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0);
2671 }
2672
2673 static DMDrawOption draw_dm_creases__setDrawOptions(void *userData, int index)
2674 {
2675         BMEditMesh *em = userData;
2676         BMEdge *eed = EDBM_edge_at_index(userData, index);
2677         float *crease = eed ? (float *)CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_CREASE) : NULL;
2678         
2679         if (!crease)
2680                 return DM_DRAW_OPTION_SKIP;
2681         
2682         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && *crease != 0.0f) {
2683                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, *crease);
2684                 return DM_DRAW_OPTION_NORMAL;
2685         }
2686         else {
2687                 return DM_DRAW_OPTION_SKIP;
2688         }
2689 }
2690 static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm)
2691 {
2692         glLineWidth(3.0);
2693         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, em);
2694         glLineWidth(1.0);
2695 }
2696
2697 static DMDrawOption draw_dm_bweights__setDrawOptions(void *userData, int index)
2698 {
2699         BMEditMesh *em = userData;
2700         BMEdge *eed = EDBM_edge_at_index(userData, index);
2701         float *bweight = (float *)CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_BWEIGHT);
2702
2703         if (!bweight)
2704                 return DM_DRAW_OPTION_SKIP;
2705         
2706         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && *bweight != 0.0f) {
2707                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, *bweight);
2708                 return DM_DRAW_OPTION_NORMAL;
2709         }
2710         else {
2711                 return DM_DRAW_OPTION_SKIP;
2712         }
2713 }
2714 static void draw_dm_bweights__mapFunc(void *userData, int index, const float co[3],
2715                                       const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2716 {
2717         BMEditMesh *em = userData;
2718         BMVert *eve = EDBM_vert_at_index(userData, index);
2719         float *bweight = (float *)CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_BWEIGHT);
2720         
2721         if (!bweight)
2722                 return;
2723         
2724         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && *bweight != 0.0f) {
2725                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, *bweight);
2726                 bglVertex3fv(co);
2727         }
2728 }
2729 static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
2730 {
2731         ToolSettings *ts = scene->toolsettings;
2732
2733         if (ts->selectmode & SCE_SELECT_VERTEX) {
2734                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2735                 bglBegin(GL_POINTS);
2736                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, em);
2737                 bglEnd();
2738         }
2739         else {
2740                 glLineWidth(3.0);
2741                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, em);
2742                 glLineWidth(1.0);
2743         }
2744 }
2745
2746 /* Second section of routines: Combine first sets to form fancy
2747  * drawing routines (for example rendering twice to get overlays).
2748  *
2749  * Also includes routines that are basic drawing but are too
2750  * specialized to be split out (like drawing creases or measurements).
2751  */
2752
2753 /* EditMesh drawing routines*/
2754
2755 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, 
2756                                 BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act,
2757                                                                 RegionView3D *rv3d)
2758 {
2759         ToolSettings *ts = scene->toolsettings;
2760         int sel;
2761
2762         if (v3d->zbuf) glDepthMask(0);      // disable write in zbuffer, zbuf select
2763
2764         for (sel = 0; sel < 2; sel++) {
2765                 unsigned char col[4], fcol[4];
2766                 int pass;
2767
2768                 UI_GetThemeColor3ubv(sel ? TH_VERTEX_SELECT : TH_VERTEX, col);
2769                 UI_GetThemeColor3ubv(sel ? TH_FACE_DOT : TH_WIRE, fcol);
2770
2771                 for (pass = 0; pass < 2; pass++) {
2772                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2773                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2774
2775                         if (pass == 0) {
2776                                 if (v3d->zbuf && !(v3d->flag & V3D_ZBUF_SELECT)) {
2777                                         glDisable(GL_DEPTH_TEST);
2778
2779                                         glEnable(GL_BLEND);
2780                                 }
2781                                 else {
2782                                         continue;
2783                                 }
2784
2785                                 size = (size > 2.1f ? size / 2.0f : size);
2786                                 fsize = (fsize > 2.1f ? fsize / 2.0f : fsize);
2787                                 col[3] = fcol[3] = 100;
2788                         }
2789                         else {
2790                                 col[3] = fcol[3] = 255;
2791                         }
2792
2793                         if (ts->selectmode & SCE_SELECT_VERTEX) {
2794                                 glPointSize(size);
2795                                 glColor4ubv(col);
2796                                 draw_dm_verts(em, cageDM, sel, eve_act, rv3d);
2797                         }
2798                         
2799                         if (check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2800                                 glPointSize(fsize);
2801                                 glColor4ubv(fcol);
2802                                 draw_dm_face_centers(em, cageDM, sel);
2803                         }
2804                         
2805                         if (pass == 0) {
2806                                 glDisable(GL_BLEND);
2807                                 glEnable(GL_DEPTH_TEST);
2808                         }
2809                 }
2810         }
2811
2812         if (v3d->zbuf) glDepthMask(1);
2813         glPointSize(1.0);
2814 }
2815
2816 static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d,
2817                                 Mesh *me, DerivedMesh *cageDM, short sel_only,
2818                                 BMEdge *eed_act)
2819 {
2820         ToolSettings *ts = scene->toolsettings;
2821         int pass;
2822         unsigned char wireCol[4], selCol[4], actCol[4];
2823
2824         /* since this function does transparant... */
2825         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2826         UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2827         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2828         
2829         /* when sel only is used, don't render wire, only selected, this is used for
2830          * textured draw mode when the 'edges' option is disabled */
2831         if (sel_only)
2832                 wireCol[3] = 0;
2833
2834         for (pass = 0; pass < 2; pass++) {
2835                 /* show wires in transparant when no zbuf clipping for select */
2836                 if (pass == 0) {
2837                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT) == 0) {
2838                                 glEnable(GL_BLEND);
2839                                 glDisable(GL_DEPTH_TEST);
2840                                 selCol[3] = 85;
2841                                 if (!sel_only) wireCol[3] = 85;
2842                         }
2843                         else {
2844                                 continue;
2845                         }
2846                 }
2847                 else {
2848                         selCol[3] = 255;
2849                         if (!sel_only) wireCol[3] = 255;
2850                 }
2851
2852                 if (ts->selectmode == SCE_SELECT_FACE) {
2853                         draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2854                 }
2855                 else if ( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {
2856                         if (cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2857                                 glShadeModel(GL_SMOOTH);
2858                                 draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol);
2859                                 glShadeModel(GL_FLAT);
2860                         }
2861                         else {
2862                                 draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2863                         }
2864                 }
2865                 else {
2866                         if (!sel_only) {
2867                                 glColor4ubv(wireCol);
2868                                 draw_dm_edges(em, cageDM);
2869                         }
2870                 }
2871
2872                 if (pass == 0) {
2873                         glDisable(GL_BLEND);
2874                         glEnable(GL_DEPTH_TEST);
2875                 }
2876         }
2877 }       
2878
2879 static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitSettings *unit)
2880 {
2881         const short txt_flag = V3D_CACHE_TEXT_ASCII | V3D_CACHE_TEXT_LOCALCLIP;
2882         Mesh *me = ob->data;
2883         float v1[3], v2[3], v3[3], vmid[3], fvec[3];
2884         char numstr[32]; /* Stores the measurement display text here */
2885         const char *conv_float; /* Use a float conversion matching the grid size */
2886         unsigned char col[4] = {0, 0, 0, 255}; /* color of the text to draw */
2887         float area; /* area of the face */
2888         float grid = unit->system ? unit->scale_length : v3d->grid;
2889         const int do_split = unit->flag & USER_UNIT_OPT_SPLIT;
2890         const int do_global = v3d->flag & V3D_GLOBAL_STATS;
2891         const int do_moving = G.moving;
2892
2893         BMIter iter;
2894         int i;
2895
2896         /* make the precision of the pronted value proportionate to the gridsize */
2897
2898         if (grid < 0.01f) conv_float = "%.6g";
2899         else if (grid < 0.1f) conv_float = "%.5g";
2900         else if (grid < 1.0f) conv_float = "%.4g";
2901         else if (grid < 10.0f) conv_float = "%.3g";
2902         else conv_float = "%.2g";
2903         
2904         if (me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2905                 BMEdge *eed;
2906
2907                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2908
2909                 eed = BM_iter_new(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
2910                 for (; eed; eed = BM_iter_step(&iter)) {
2911                         /* draw selected edges, or edges next to selected verts while draging */
2912                         if (BM_elem_flag_test(eed, BM_ELEM_SELECT) ||
2913                             (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
2914                                            BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))))
2915                         {
2916
2917                                 copy_v3_v3(v1, eed->v1->co);
2918                                 copy_v3_v3(v2, eed->v2->co);
2919
2920                                 mid_v3_v3v3(vmid, v1, v2);
2921
2922                                 if (do_global) {
2923                                         mul_mat3_m4_v3(ob->obmat, v1);
2924                                         mul_mat3_m4_v3(ob->obmat, v2);
2925                                 }
2926
2927                                 if (unit->system) {
2928                                         bUnit_AsString(numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3,
2929                                                        unit->system, B_UNIT_LENGTH, do_split, FALSE);
2930                                 }
2931                                 else {
2932                                         sprintf(numstr, conv_float, len_v3v3(v1, v2));
2933                                 }
2934
2935                                 view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);
2936                         }
2937                 }
2938         }
2939
2940         if (me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2941                 /* would be nice to use BM_face_calc_area, but that is for 2d faces
2942                  * so instead add up tessellation triangle areas */
2943                 BMFace *f;
2944                 int n;
2945
2946 #define DRAW_EM_MEASURE_STATS_FACEAREA()                                      \
2947         if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {                               \
2948                 mul_v3_fl(vmid, 1.0f / (float)n);                                     \
2949                 if (unit->system)                                                     \
2950                         bUnit_AsString(numstr, sizeof(numstr),                            \
2951                                        (double)(area * unit->scale_length),               \
2952                                        3, unit->system, B_UNIT_LENGTH, do_split, FALSE);  \
2953                 else                                                                  \
2954                         BLI_snprintf(numstr, sizeof(numstr), conv_float, area);           \
2955                 view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);          \
2956         }
2957
2958                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2959                 
2960                 f = NULL;
2961                 area = 0.0;
2962                 zero_v3(vmid);
2963                 n = 0;
2964                 for (i = 0; i < em->tottri; i++) {
2965                         BMLoop **l = em->looptris[i];
2966                         if (f && l[0]->f != f) {
2967                                 DRAW_EM_MEASURE_STATS_FACEAREA();
2968                                 zero_v3(vmid);
2969                                 area = 0.0;
2970                                 n = 0;
2971                         }
2972
2973                         f = l[0]->f;
2974                         copy_v3_v3(v1, l[0]->v->co);
2975                         copy_v3_v3(v2, l[1]->v->co);
2976                         copy_v3_v3(v3, l[2]->v->co);
2977                         if (do_global) {
2978                                 mul_mat3_m4_v3(ob->obmat, v1);
2979                                 mul_mat3_m4_v3(ob->obmat, v2);
2980                                 mul_mat3_m4_v3(ob->obmat, v3);
2981                         }
2982                         area += area_tri_v3(v1, v2, v3);
2983                         add_v3_v3(vmid, v1);
2984                         add_v3_v3(vmid, v2);
2985                         add_v3_v3(vmid, v3);
2986                         n += 3;
2987                 }
2988
2989                 if (f) {
2990                         DRAW_EM_MEASURE_STATS_FACEAREA();
2991                 }
2992 #undef DRAW_EM_MEASURE_STATS_FACEAREA
2993         }
2994
2995         if (me->drawflag & ME_DRAWEXTRA_FACEANG) {
2996                 BMFace *efa;
2997                 int is_rad = unit->system_rotation == USER_UNIT_ROT_RADIANS;
2998
2999                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
3000
3001
3002                 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
3003                         const int is_face_sel = BM_elem_flag_test(efa, BM_ELEM_SELECT);
3004
3005                         if (is_face_sel || do_moving) {
3006                                 BMIter liter;
3007                                 BMLoop *loop;
3008                                 int is_first = TRUE;
3009
3010                                 BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) {
3011                                         if (is_face_sel || (do_moving && BM_elem_flag_test(loop->v, BM_ELEM_SELECT))) {
3012                                                 float angle;
3013
3014                                                 /* lazy init center calc */
3015                                                 if (is_first) {
3016                                                         BM_face_calc_center_bounds(efa, vmid);
3017                                                         /* Avoid triple matrix multiply every vertex for 'global' */
3018                                                         if (do_global) {
3019                                                                 copy_v3_v3(v1, loop->prev->v->co);
3020                                                                 copy_v3_v3(v2, loop->v->co);
3021                                                                 mul_mat3_m4_v3(ob->obmat, v1);
3022                                                                 mul_mat3_m4_v3(ob->obmat, v2);
3023                                                         }
3024                                                         is_first = FALSE;
3025                                                 }
3026
3027                                                 if (do_global) {
3028                                                         copy_v3_v3(v3, loop->next->v->co);
3029
3030                                                         mul_mat3_m4_v3(ob->obmat, v3);
3031
3032                                                         angle = angle_v3v3v3(v1, v2, v3);
3033                                                         interp_v3_v3v3(fvec, vmid, v2, 0.8f);
3034                                                         copy_v3_v3(v1, v2);
3035                                                         copy_v3_v3(v2, v3);
3036                                                 }
3037                                                 else {
3038                                                         angle = angle_v3v3v3(loop->prev->v->co, loop->v->co, loop->next->v->co);
3039                                                         interp_v3_v3v3(fvec, vmid, loop->v->co, 0.8f);
3040                                                 }
3041
3042                                                 BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
3043                                                 view3d_cached_text_draw_add(fvec, numstr, 0, txt_flag, col);
3044                                         }
3045                                 }
3046                         }
3047                 }
3048         }
3049 }
3050
3051 static void draw_em_indices(BMEditMesh *em)
3052 {
3053         const short txt_flag = V3D_CACHE_TEXT_ASCII | V3D_CACHE_TEXT_LOCALCLIP;
3054         BMEdge *e;
3055         BMFace *f;
3056         BMVert *v;
3057         int i;
3058         char numstr[32];
3059         float pos[3];
3060         unsigned char col[4];
3061
3062         BMIter iter;
3063         BMesh *bm = em->bm;
3064
3065         /* For now, reuse appropriate theme colors from stats text colors */
3066         i = 0;
3067         if (em->selectmode & SCE_SELECT_VERTEX) {
3068                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
3069                 BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
3070                         if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
3071                                 sprintf(numstr, "%d", i);
3072                                 view3d_cached_text_draw_add(v->co, numstr, 0, txt_flag, col);
3073                         }
3074                         i++;
3075                 }
3076         }
3077
3078         if (em->selectmode & SCE_SELECT_EDGE) {
3079                 i = 0;
3080                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
3081                 BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
3082                         if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
3083                                 sprintf(numstr, "%d", i);
3084                                 mid_v3_v3v3(pos, e->v1->co, e->v2->co);
3085                                 view3d_cached_text_draw_add(pos, numstr, 0, txt_flag, col);
3086                         }
3087                         i++;
3088                 }
3089         }
3090
3091         if (em->selectmode & SCE_SELECT_FACE) {
3092                 i = 0;
3093                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
3094                 BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
3095                         if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
3096                                 BM_face_calc_center_mean(f, pos);
3097                                 sprintf(numstr, "%d", i);
3098                                 view3d_cached_text_draw_add(pos, numstr, 0, txt_flag, col);
3099                         }
3100                         i++;
3101                 }
3102         }
3103 }
3104
3105 static DMDrawOption draw_em_fancy__setFaceOpts(void *userData, int index)
3106 {
3107         BMFace *efa = EDBM_face_at_index(userData, index);
3108
3109         if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
3110                 GPU_enable_material(efa->mat_nr + 1, NULL);
3111                 return DM_DRAW_OPTION_NORMAL;
3112         }
3113         else
3114                 return DM_DRAW_OPTION_SKIP;
3115 }
3116
3117 static DMDrawOption draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
3118 {
3119         BMFace *efa = EDBM_face_at_index(userData, index);
3120
3121         if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
3122                 return DM_DRAW_OPTION_SKIP;
3123         else
3124                 return DM_DRAW_OPTION_NORMAL;
3125 }
3126
3127 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
3128                           Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
3129
3130 {
3131         Mesh *me = ob->data;
3132         BMFace *efa_act = BM_active_face_get(em->bm, FALSE); /* annoying but active faces is stored differently */
3133         BMEdge *eed_act = NULL;
3134         BMVert *eve_act = NULL;
3135         
3136         if (em->bm->selected.last) {
3137                 BMEditSelection *ese = em->bm->selected.last;
3138                 /* face is handeled above */
3139 #if 0
3140                 if (ese->type == BM_FACE) {
3141                         efa_act = (BMFace *)ese->data;
3142                 }
3143                 else 
3144 #endif
3145                 if (ese->htype == BM_EDGE) {
3146                         eed_act = (BMEdge *)ese->ele;
3147                 }
3148                 else if (ese->htype == BM_VERT) {
3149                         eve_act = (BMVert *)ese->ele;
3150                 }
3151         }
3152         
3153         EDBM_index_arrays_init(em, 1, 1, 1);
3154
3155         if (dt > OB_WIRE) {