merge with/from trunk at r35190
[blender.git] / source / blender / editors / uvedit / uvedit_draw.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation, 2002-2009
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include <float.h>
29 #include <math.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include "MEM_guardedalloc.h"
34
35 #include "DNA_mesh_types.h"
36 #include "DNA_meshdata_types.h"
37 #include "DNA_object_types.h"
38 #include "DNA_scene_types.h"
39 #include "DNA_screen_types.h"
40 #include "DNA_space_types.h"
41
42 #include "BLI_math.h"
43 #include "BLI_editVert.h"
44 #include "BLI_utildefines.h"
45
46 #include "BKE_DerivedMesh.h"
47 #include "BKE_mesh.h"
48 #include "BKE_tessmesh.h"
49
50 #include "BLI_array.h"
51
52 #include "BIF_gl.h"
53 #include "BIF_glutil.h"
54
55 #include "ED_util.h"
56 #include "ED_image.h"
57 #include "ED_mesh.h"
58 #include "ED_uvedit.h"
59
60 #include "UI_resources.h"
61
62 #include "uvedit_intern.h"
63
64 static void drawcursor_sima(SpaceImage *sima, ARegion *ar)
65 {
66         float zoomx, zoomy, w, h;
67         int width, height;
68
69         ED_space_image_size(sima, &width, &height);
70         ED_space_image_zoom(sima, ar, &zoomx, &zoomy);
71
72         w= zoomx*width/256.0f;
73         h= zoomy*height/256.0f;
74         
75         cpack(0xFFFFFF);
76         glTranslatef(sima->cursor[0], sima->cursor[1], 0.0f);  
77         fdrawline(-0.05/w, 0, 0, 0.05/h);
78         fdrawline(0, 0.05/h, 0.05/w, 0);
79         fdrawline(0.05/w, 0, 0, -0.05/h);
80         fdrawline(0, -0.05/h, -0.05/w, 0);
81         
82         setlinestyle(4);
83         cpack(0xFF);
84         fdrawline(-0.05/w, 0, 0, 0.05/h);
85         fdrawline(0, 0.05/h, 0.05/w, 0);
86         fdrawline(0.05/w, 0, 0, -0.05/h);
87         fdrawline(0, -0.05/h, -0.05/w, 0);
88         
89         
90         setlinestyle(0);
91         cpack(0x0);
92         fdrawline(-0.020/w, 0, -0.1/w, 0);
93         fdrawline(0.1/w, 0, .020/w, 0);
94         fdrawline(0, -0.020/h, 0, -0.1/h);
95         fdrawline(0, 0.1/h, 0, 0.020/h);
96         
97         setlinestyle(1);
98         cpack(0xFFFFFF);
99         fdrawline(-0.020/w, 0, -0.1/w, 0);
100         fdrawline(0.1/w, 0, .020/w, 0);
101         fdrawline(0, -0.020/h, 0, -0.1/h);
102         fdrawline(0, 0.1/h, 0, 0.020/h);
103         
104         glTranslatef(-sima->cursor[0], -sima->cursor[1], 0.0f);
105         setlinestyle(0);
106 }
107
108 static int draw_uvs_face_check(Scene *scene)
109 {
110         ToolSettings *ts= scene->toolsettings;
111
112         /* checks if we are selecting only faces */
113         if(ts->uv_flag & UV_SYNC_SELECTION) {
114                 if(ts->selectmode == SCE_SELECT_FACE)
115                         return 2;
116                 else if(ts->selectmode & SCE_SELECT_FACE)
117                         return 1;
118                 else
119                         return 0;
120         }
121         else
122                 return (ts->uv_selectmode == UV_SELECT_FACE);
123 }
124
125 static void draw_uvs_shadow(Object *obedit)
126 {
127         BMEditMesh *em;
128         BMFace *efa;
129         BMLoop *l;
130         BMIter iter, liter;
131         MLoopUV *luv;
132         
133         em= ((Mesh*)obedit->data)->edit_btmesh;
134
135         /* draws the grey mesh when painting */
136         glColor3ub(112, 112, 112);
137
138         BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
139                 glBegin(GL_LINE_LOOP);
140                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
141                         luv= CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
142
143                         glVertex2fv(luv->uv);
144                 }
145                 glEnd();
146         }
147 }
148
149 static int draw_uvs_dm_shadow(DerivedMesh *dm)
150 {
151         /* draw shadow mesh - this is the mesh with the modifier applied */
152
153         if(dm && dm->drawUVEdges && CustomData_has_layer(&dm->loopData, CD_MLOOPUV)) {
154                 glColor3ub(112, 112, 112);
155                 dm->drawUVEdges(dm);
156                 return 1;
157         }
158
159         return 0;
160 }
161
162 static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTexPoly *activetf)
163 {
164         BMFace *efa;
165         BMLoop *l;
166         BMIter iter, liter;
167         MTexPoly *tf;
168         MLoopUV *luv;
169         Image *ima= sima->image;
170         BLI_array_declare(tf_uv);
171         BLI_array_declare(tf_uvorig);
172         float aspx, aspy, col[4], (*tf_uv)[2] = NULL, (*tf_uvorig)[2] = NULL;
173         int i;
174
175         ED_space_image_uv_aspect(sima, &aspx, &aspy);
176         
177         switch(sima->dt_uvstretch) {
178                 case SI_UVDT_STRETCH_AREA:
179                 {
180                         float totarea=0.0f, totuvarea=0.0f, areadiff, uvarea, area;
181                         
182                         BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
183                                 tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
184                                 
185                                 BLI_array_empty(tf_uv);
186                                 BLI_array_empty(tf_uvorig);
187                                 
188                                 i = 0;
189                                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
190                                         luv= CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
191                                         BLI_array_growone(tf_uv);
192                                         BLI_array_growone(tf_uvorig);
193
194                                         tf_uvorig[i][0] = luv->uv[0];
195                                         tf_uvorig[i][1] = luv->uv[1];
196
197                                         i++;
198                                 }
199
200                                 poly_copy_aspect(tf_uvorig, tf_uv, aspx, aspy, efa->len);
201
202                                 totarea += BM_face_area(efa);
203                                 //totuvarea += tf_area(tf, efa->v4!=0);
204                                 totuvarea += poly_uv_area(tf_uv, efa->len);
205                                 
206                                 if(uvedit_face_visible(scene, ima, efa, tf)) {
207                                         BMINDEX_SET(efa, 1);
208                                 }
209                                 else {
210                                         if(tf == activetf)
211                                                 activetf= NULL;
212                                         BMINDEX_SET(efa, 0);
213                                 }
214                         }
215                         
216                         if(totarea < FLT_EPSILON || totuvarea < FLT_EPSILON) {
217                                 col[0] = 1.0;
218                                 col[1] = col[2] = 0.0;
219                                 glColor3fv(col);
220                                 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
221                                         if(BMINDEX_GET(efa)) {
222                                                 glBegin(GL_POLYGON);
223                                                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
224                                                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
225                                                         glVertex2fv(luv->uv);
226                                                 }
227                                                 glEnd();
228                                         }
229                                 }
230                         }
231                         else {
232                                 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
233                                         if(BMINDEX_GET(efa)) {
234                                                 area = BM_face_area(efa) / totarea;
235
236                                                 BLI_array_empty(tf_uv);
237                                                 BLI_array_empty(tf_uvorig);
238
239                                                 i = 0;
240                                                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
241                                                         luv= CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
242                                                         BLI_array_growone(tf_uv);
243                                                         BLI_array_growone(tf_uvorig);
244
245                                                         tf_uvorig[i][0] = luv->uv[0];
246                                                         tf_uvorig[i][1] = luv->uv[1];
247
248                                                         i++;
249                                                 }
250
251                                                 poly_copy_aspect(tf_uvorig, tf_uv, aspx, aspy, efa->len);
252
253                                                 //uvarea = tf_area(tf, efa->v4!=0) / totuvarea;
254                                                 uvarea = poly_uv_area(tf_uv, efa->len) / totuvarea;
255                                                 
256                                                 if(area < FLT_EPSILON || uvarea < FLT_EPSILON)
257                                                         areadiff = 1.0;
258                                                 else if(area>uvarea)
259                                                         areadiff = 1.0-(uvarea/area);
260                                                 else
261                                                         areadiff = 1.0-(area/uvarea);
262                                                 
263                                                 weight_to_rgb(areadiff, col, col+1, col+2);
264                                                 glColor3fv(col);
265                                                 
266                                                 glBegin(GL_POLYGON);
267                                                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
268                                                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
269                                                         glVertex2fv(luv->uv);
270                                                 }
271                                                 glEnd();
272                                         }
273                                 }
274                         }
275                         break;
276                 }
277                 case SI_UVDT_STRETCH_ANGLE:
278                 {
279 #if 0 //BMESH_TODO
280                         float uvang1,uvang2,uvang3,uvang4;
281                         float ang1,ang2,ang3,ang4;
282                         float av1[3], av2[3], av3[3], av4[3]; /* use for 2d and 3d  angle vectors */
283                         float a;
284                         
285                         col[3] = 0.5; /* hard coded alpha, not that nice */
286                         
287                         glShadeModel(GL_SMOOTH);
288                         
289                         for(efa= em->faces.first; efa; efa= efa->next) {
290                                 tf= CustomData_em_get(&em->fdata, efa->head.data, CD_MTFACE);
291                                 
292                                 if(uvedit_face_visible(scene, ima, efa, tf)) {
293                                         efa->tmp.p = tf;
294                                         uv_copy_aspect(tf->uv, tf_uv, aspx, aspy);
295                                         if(efa->v4) {
296                                                 
297 #if 0                                           /* Simple but slow, better reuse normalized vectors */
298                                                 uvang1 = RAD2DEG(angle_v2v2v2(tf_uv[3], tf_uv[0], tf_uv[1]));
299                                                 ang1 = RAD2DEG(angle_v3v3v3(efa->v4->co, efa->v1->co, efa->v2->co));
300                                                 
301                                                 uvang2 = RAD2DEG(angle_v2v2v2(tf_uv[0], tf_uv[1], tf_uv[2]));
302                                                 ang2 = RAD2DEG(angle_v3v3v3(efa->v1->co, efa->v2->co, efa->v3->co));
303                                                 
304                                                 uvang3 = RAD2DEG(angle_v2v2v2(tf_uv[1], tf_uv[2], tf_uv[3]));
305                                                 ang3 = RAD2DEG(angle_v3v3v3(efa->v2->co, efa->v3->co, efa->v4->co));
306                                                 
307                                                 uvang4 = RAD2DEG(angle_v2v2v2(tf_uv[2], tf_uv[3], tf_uv[0]));
308                                                 ang4 = RAD2DEG(angle_v3v3v3(efa->v3->co, efa->v4->co, efa->v1->co));
309 #endif
310                                                 
311                                                 /* uv angles */
312                                                 VECSUB2D(av1, tf_uv[3], tf_uv[0]); normalize_v2(av1);
313                                                 VECSUB2D(av2, tf_uv[0], tf_uv[1]); normalize_v2(av2);
314                                                 VECSUB2D(av3, tf_uv[1], tf_uv[2]); normalize_v2(av3);
315                                                 VECSUB2D(av4, tf_uv[2], tf_uv[3]); normalize_v2(av4);
316                                                 
317                                                 /* This is the correct angle however we are only comparing angles
318                                                  * uvang1 = 90-((angle_normalized_v2v2(av1, av2) * 180.0/M_PI)-90);*/
319                                                 uvang1 = angle_normalized_v2v2(av1, av2)*180.0/M_PI;
320                                                 uvang2 = angle_normalized_v2v2(av2, av3)*180.0/M_PI;
321                                                 uvang3 = angle_normalized_v2v2(av3, av4)*180.0/M_PI;
322                                                 uvang4 = angle_normalized_v2v2(av4, av1)*180.0/M_PI;
323                                                 
324                                                 /* 3d angles */
325                                                 VECSUB(av1, efa->v4->co, efa->v1->co); normalize_v3(av1);
326                                                 VECSUB(av2, efa->v1->co, efa->v2->co); normalize_v3(av2);
327                                                 VECSUB(av3, efa->v2->co, efa->v3->co); normalize_v3(av3);
328                                                 VECSUB(av4, efa->v3->co, efa->v4->co); normalize_v3(av4);
329                                                 
330                                                 /* This is the correct angle however we are only comparing angles
331                                                  * ang1 = 90-((angle_normalized_v3v3(av1, av2) * 180.0/M_PI)-90);*/
332                                                 ang1 = angle_normalized_v3v3(av1, av2)*180.0/M_PI;
333                                                 ang2 = angle_normalized_v3v3(av2, av3)*180.0/M_PI;
334                                                 ang3 = angle_normalized_v3v3(av3, av4)*180.0/M_PI;
335                                                 ang4 = angle_normalized_v3v3(av4, av1)*180.0/M_PI;
336                                                 
337                                                 glBegin(GL_QUADS);
338                                                 
339                                                 /* This simple makes the angles display worse then they really are ;)
340                                                  * 1.0-pow((1.0-a), 2) */
341                                                 
342                                                 a = fabs(uvang1-ang1)/180.0;
343                                                 weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
344                                                 glColor3fv(col);
345                                                 glVertex2fv(tf->uv[0]);
346                                                 a = fabs(uvang2-ang2)/180.0;
347                                                 weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
348                                                 glColor3fv(col);
349                                                 glVertex2fv(tf->uv[1]);
350                                                 a = fabs(uvang3-ang3)/180.0;
351                                                 weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
352                                                 glColor3fv(col);
353                                                 glVertex2fv(tf->uv[2]);
354                                                 a = fabs(uvang4-ang4)/180.0;
355                                                 weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
356                                                 glColor3fv(col);
357                                                 glVertex2fv(tf->uv[3]);
358                                                 
359                                         }
360                                         else {
361 #if 0                                           /* Simple but slow, better reuse normalized vectors */
362                                                 uvang1 = RAD2DEG(angle_v2v2v2(tf_uv[2], tf_uv[0], tf_uv[1]));
363                                                 ang1 = RAD2DEG(angle_v3v3v3(efa->v3->co, efa->v1->co, efa->v2->co));
364                                                 
365                                                 uvang2 = RAD2DEG(angle_v2v2v2(tf_uv[0], tf_uv[1], tf_uv[2]));
366                                                 ang2 = RAD2DEG(angle_v3v3v3(efa->v1->co, efa->v2->co, efa->v3->co));
367                                                 
368                                                 uvang3 = M_PI-(uvang1+uvang2);
369                                                 ang3 = M_PI-(ang1+ang2);
370 #endif                                          
371                                                 
372                                                 /* uv angles */
373                                                 VECSUB2D(av1, tf_uv[2], tf_uv[0]); normalize_v2(av1);
374                                                 VECSUB2D(av2, tf_uv[0], tf_uv[1]); normalize_v2(av2);
375                                                 VECSUB2D(av3, tf_uv[1], tf_uv[2]); normalize_v2(av3);
376                                                 
377                                                 /* This is the correct angle however we are only comparing angles
378                                                  * uvang1 = 90-((angle_normalized_v2v2(av1, av2) * 180.0/M_PI)-90); */
379                                                 uvang1 = angle_normalized_v2v2(av1, av2)*180.0/M_PI;
380                                                 uvang2 = angle_normalized_v2v2(av2, av3)*180.0/M_PI;
381                                                 uvang3 = angle_normalized_v2v2(av3, av1)*180.0/M_PI;
382                                                 
383                                                 /* 3d angles */
384                                                 VECSUB(av1, efa->v3->co, efa->v1->co); normalize_v3(av1);
385                                                 VECSUB(av2, efa->v1->co, efa->v2->co); normalize_v3(av2);
386                                                 VECSUB(av3, efa->v2->co, efa->v3->co); normalize_v3(av3);
387                                                 /* This is the correct angle however we are only comparing angles
388                                                  * ang1 = 90-((angle_normalized_v3v3(av1, av2) * 180.0/M_PI)-90); */
389                                                 ang1 = angle_normalized_v3v3(av1, av2)*180.0/M_PI;
390                                                 ang2 = angle_normalized_v3v3(av2, av3)*180.0/M_PI;
391                                                 ang3 = angle_normalized_v3v3(av3, av1)*180.0/M_PI;
392                                                 
393                                                 /* This simple makes the angles display worse then they really are ;)
394                                                  * 1.0-pow((1.0-a), 2) */
395                                                 
396                                                 glBegin(GL_TRIANGLES);
397                                                 a = fabs(uvang1-ang1)/180.0;
398                                                 weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
399                                                 glColor3fv(col);
400                                                 glVertex2fv(tf->uv[0]);
401                                                 a = fabs(uvang2-ang2)/180.0;
402                                                 weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
403                                                 glColor3fv(col);
404                                                 glVertex2fv(tf->uv[1]);
405                                                 a = fabs(uvang3-ang3)/180.0;
406                                                 weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
407                                                 glColor3fv(col);
408                                                 glVertex2fv(tf->uv[2]);
409                                         }
410                                         glEnd();
411                                 }
412                                 else {
413                                         if(tf == activetf)
414                                                 activetf= NULL;
415                                         efa->tmp.p = NULL;
416                                 }
417                         }
418
419                         glShadeModel(GL_FLAT);
420                         break;
421
422 #endif
423                 }
424         }
425 }
426
427 static void draw_uvs_other(Scene *scene, Object *obedit, MTexPoly *activetf)
428 {
429         Base *base;
430         Image *curimage;
431
432         curimage= (activetf)? activetf->tpage: NULL;
433
434         glColor3ub(96, 96, 96);
435
436         for(base=scene->base.first; base; base=base->next) {
437                 Object *ob= base->object;
438
439                 if(!(base->flag & SELECT)) continue;
440                 if(!(base->lay & scene->lay)) continue;
441                 if(ob->restrictflag & OB_RESTRICT_VIEW) continue;
442
443                 if((ob->type==OB_MESH) && (ob!=obedit)) {
444                         Mesh *me= ob->data;
445
446                         if(me->mtface) {
447                                 MPoly *mface= me->mpoly;
448                                 MTexPoly *tface= me->mtpoly;
449                                 MLoopUV *mloopuv;
450                                 int a, b;
451
452                                 for(a=me->totpoly; a>0; a--, tface++, mface++) {
453                                         if(tface->tpage == curimage) {
454                                                 glBegin(GL_LINE_LOOP);
455
456                                                 mloopuv = me->mloopuv + mface->loopstart;
457                                                 for (b=0; b<mface->totloop; b++, mloopuv++) {
458                                                         glVertex2fv(mloopuv->uv);
459                                                 }
460                                                 glEnd();
461                                         }
462                                 }
463                         }
464                 }
465         }
466 }
467
468 /* draws uv's in the image space */
469 static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
470 {
471         ToolSettings *ts;
472         Mesh *me= obedit->data;
473         BMEditMesh *em;
474         BMFace *efa, *efa_act, *activef;
475         BMLoop *l;
476         BMIter iter, liter;
477         MTexPoly *tf, *activetf = NULL;
478         MLoopUV *luv;
479         DerivedMesh *finaldm, *cagedm;
480         unsigned char col1[4], col2[4];
481         float pointsize;
482         int drawfaces, interpedges;
483         int i;
484         Image *ima= sima->image;
485         
486         em= me->edit_btmesh;
487         activetf= EDBM_get_active_mtexpoly(em, &efa_act, 0); /* will be set to NULL if hidden */
488         activef = EDBM_get_actFace(em, 0);
489         ts= scene->toolsettings;
490
491         drawfaces= draw_uvs_face_check(scene);
492         if(ts->uv_flag & UV_SYNC_SELECTION)
493                 interpedges= (ts->selectmode & SCE_SELECT_VERTEX);
494         else
495                 interpedges= (ts->uv_selectmode == UV_SELECT_VERTEX);
496         
497         /* draw other uvs */
498         if(sima->flag & SI_DRAW_OTHER)
499                 draw_uvs_other(scene, obedit, activetf);
500
501         /* 1. draw shadow mesh */
502         
503         if(sima->flag & SI_DRAWSHADOW) {
504                 /* first try existing derivedmesh */
505                 if(!draw_uvs_dm_shadow(em->derivedFinal)) {
506                         /* create one if it does not exist */
507                         cagedm = editbmesh_get_derived_cage_and_final(scene, obedit, me->edit_btmesh, &finaldm, CD_MASK_BAREMESH|CD_MASK_MTFACE);
508
509                         /* when sync selection is enabled, all faces are drawn (except for hidden)
510                          * so if cage is the same as the final, theres no point in drawing this */
511                         if(!((ts->uv_flag & UV_SYNC_SELECTION) && (cagedm == finaldm)))
512                                 draw_uvs_dm_shadow(finaldm);
513                         
514                         /* release derivedmesh again */
515                         if(cagedm != finaldm) cagedm->release(cagedm);
516                         finaldm->release(finaldm);
517                 }
518         }
519         
520         /* 2. draw colored faces */
521         
522         if(sima->flag & SI_DRAW_STRETCH) {
523                 draw_uvs_stretch(sima, scene, em, activetf);
524         }
525         else if(me->drawflag & ME_DRAWFACES) {
526                 /* draw transparent faces */
527                 UI_GetThemeColor4ubv(TH_FACE, col1);
528                 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
529                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
530                 glEnable(GL_BLEND);
531                 
532                 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
533                         tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
534                         
535                         if(uvedit_face_visible(scene, ima, efa, tf)) {
536                                 BMINDEX_SET(efa, 1);
537                                 if(tf==activetf) continue; /* important the temp boolean is set above */
538
539                                 if(uvedit_face_selected(scene, em, efa))
540                                         glColor4ubv((GLubyte *)col2);
541                                 else
542                                         glColor4ubv((GLubyte *)col1);
543                                 
544                                 glBegin(GL_POLYGON);
545                                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
546                                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
547                                         glVertex2fv(luv->uv);
548                                 }
549                                 glEnd();
550                         }
551                         else {
552                                 if(tf == activetf)
553                                         activetf= NULL;
554                                 BMINDEX_SET(efa, 0);
555                         }
556                 }
557                 glDisable(GL_BLEND);
558         }
559         else {
560                 /* would be nice to do this within a draw loop but most below are optional, so it would involve too many checks */
561                 
562                 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
563                         tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
564
565                         if(uvedit_face_visible(scene, ima, efa, tf)) {          
566                                 BMINDEX_SET(efa, 1);
567                         }
568                         else {
569                                 if(tf == activetf)
570                                         activetf= NULL;
571                                 BMINDEX_SET(efa, 0);
572                         }
573                 }
574                 
575         }
576         
577         /* 3. draw active face stippled */
578
579         if(activef) {
580                 glEnable(GL_BLEND);
581                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
582                 UI_ThemeColor4(TH_EDITMESH_ACTIVE);
583
584                 glEnable(GL_POLYGON_STIPPLE);
585                 glPolygonStipple(stipple_quarttone);
586
587                 glBegin(GL_POLYGON);
588                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, activef) {
589                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
590                         glVertex2fv(luv->uv);
591                 }
592                 glEnd();
593
594                 glDisable(GL_POLYGON_STIPPLE);
595                 glDisable(GL_BLEND);
596         }
597         
598         /* 4. draw edges */
599
600         if(sima->flag & SI_SMOOTH_UV) {
601                 glEnable(GL_LINE_SMOOTH);
602                 glEnable(GL_BLEND);
603                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
604         }
605         
606         switch(sima->dt_uv) {
607                 case SI_UVDT_DASH:
608                         BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
609                                 if (!BMINDEX_GET(efa))
610                                         continue;
611                                 tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
612
613                                 if(tf) {
614                                         cpack(0x111111);
615
616                                         glBegin(GL_LINE_LOOP);
617                                         BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
618                                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
619                                                 glVertex2fv(luv->uv);
620                                         }
621                                         glEnd();
622
623                                         setlinestyle(2);
624                                         cpack(0x909090);
625
626                                         glBegin(GL_LINE_LOOP);
627                                         BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
628                                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
629                                                 glVertex2fv(luv->uv);
630                                         }
631                                         glEnd();
632
633                                         /*glBegin(GL_LINE_STRIP);
634                                                 luv = CustomData_bmesh_get(&em->bm->ldata, efa->lbase->head.data, CD_MLOOPUV);
635                                                 glVertex2fv(luv->uv);
636                                                 luv = CustomData_bmesh_get(&em->bm->ldata, efa->lbase->next->head.data, CD_MLOOPUV);
637                                                 glVertex2fv(luv->uv);
638                                         glEnd();*/
639
640                                         setlinestyle(0);
641                                 }
642                         }
643                         break;
644                 case SI_UVDT_BLACK: /* black/white */
645                 case SI_UVDT_WHITE: 
646                         if(sima->dt_uv==SI_UVDT_WHITE) glColor3f(1.0f, 1.0f, 1.0f);
647                         else glColor3f(0.0f, 0.0f, 0.0f);
648
649                         BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
650                                 if (!BMINDEX_GET(efa))
651                                         continue;
652
653                                 glBegin(GL_LINE_LOOP);
654                                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
655                                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
656                                         glVertex2fv(luv->uv);
657                                 }
658                                 glEnd();
659                         }
660                         break;
661                 case SI_UVDT_OUTLINE:
662                         glLineWidth(3);
663                         cpack(0x0);
664                         
665                         BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
666                                 if (!BMINDEX_GET(efa))
667                                         continue;
668
669                                 glBegin(GL_LINE_LOOP);
670                                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
671                                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
672                                         glVertex2fv(luv->uv);
673                                 }
674                                 glEnd();
675                         }
676                         
677                         glLineWidth(1);
678                         col2[0] = col2[1] = col2[2] = 192; col2[3] = 255;
679                         glColor4ubv((unsigned char *)col2); 
680                         
681                         if(me->drawflag & ME_DRAWEDGES) {
682                                 int lastsel= 0, sel;
683                                 UI_GetThemeColor4ubv(TH_VERTEX_SELECT, col1);
684
685                                 if(interpedges) {
686                                         glShadeModel(GL_SMOOTH);
687
688                                         BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
689                                                 if (!BMINDEX_GET(efa))
690                                                         continue;
691
692                                                 glBegin(GL_LINE_LOOP);
693                                                 i = 0;
694                                                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
695                                                         sel = (uvedit_uv_selected(em, scene, l)? 1 : 0);
696                                                         if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
697
698                                                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
699                                                         glVertex2fv(luv->uv);
700                                                         luv = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV);
701                                                         glVertex2fv(luv->uv);
702                                                         i += 1;
703                                                 }
704                                                 glEnd();
705                                         }
706
707                                         glShadeModel(GL_FLAT);
708                                 }
709                                 else {
710                                         BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
711                                                 if (!BMINDEX_GET(efa))
712                                                         continue;
713
714                                                 glBegin(GL_LINE_LOOP);
715                                                 i = 0;
716                                                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
717                                                         sel = (uvedit_edge_selected(em, scene, l)? 1 : 0);
718                                                         if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
719
720                                                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
721                                                         glVertex2fv(luv->uv);
722                                                         luv = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV);
723                                                         glVertex2fv(luv->uv);
724                                                         i += 1;
725                                                 }
726                                                 glEnd();
727                                         }
728                                 }
729                         }
730                         else {
731                                 /* no nice edges */
732                                 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
733                                         if (!BMINDEX_GET(efa))
734                                                 continue;
735                                 
736                                         glBegin(GL_LINE_LOOP);
737                                         BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
738                                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
739                                                 glVertex2fv(luv->uv);
740                                         }
741                                         glEnd();
742                                 }
743                         }
744                         
745                         break;
746         }
747
748         if(sima->flag & SI_SMOOTH_UV) {
749                 glDisable(GL_LINE_SMOOTH);
750                 glDisable(GL_BLEND);
751         }
752
753         /* 5. draw face centers */
754
755         if(drawfaces) {
756                 float cent[2];
757                 
758                 pointsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
759                 glPointSize(pointsize); // TODO - drawobject.c changes this value after - Investigate!
760                 
761                 /* unselected faces */
762                 UI_ThemeColor(TH_WIRE);
763
764                 bglBegin(GL_POINTS);
765                 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
766                         if (!BMINDEX_GET(efa))
767                                 continue;
768
769                         if(!uvedit_face_selected(scene, em, efa)) {
770                                 poly_uv_center(em, efa, cent);
771                                 bglVertex2fv(cent);
772                         }
773                 }
774                 bglEnd();
775
776                 /* selected faces */
777                 UI_ThemeColor(TH_FACE_DOT);
778
779                 bglBegin(GL_POINTS);
780                 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
781                         if (!BMINDEX_GET(efa))
782                                 continue;
783
784                         if(uvedit_face_selected(scene, em, efa)) {
785                                 poly_uv_center(em, efa, cent);
786                                 bglVertex2fv(cent);
787                         }
788                 }
789                 bglEnd();
790         }
791
792         /* 6. draw uv vertices */
793         
794         if(drawfaces != 2) { /* 2 means Mesh Face Mode */
795                 /* unselected uvs */
796                 UI_ThemeColor(TH_VERTEX);
797                 pointsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
798                 glPointSize(pointsize);
799         
800                 bglBegin(GL_POINTS);
801                 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
802                         if (!BMINDEX_GET(efa))
803                                 continue;
804
805                         BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
806                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
807                                 if(!uvedit_uv_selected(em, scene, l))
808                                         bglVertex2fv(luv->uv);
809                         }
810                 }
811                 bglEnd();
812         
813                 /* pinned uvs */
814                 /* give odd pointsizes odd pin pointsizes */
815                 glPointSize(pointsize*2 + (((int)pointsize % 2)? (-1): 0));
816                 cpack(0xFF);
817         
818                 bglBegin(GL_POINTS);
819                 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
820                         if (!BMINDEX_GET(efa))
821                                 continue;
822
823                         BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
824                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
825
826                                 if(luv->flag & MLOOPUV_PINNED)
827                                         bglVertex2fv(luv->uv);
828                         }
829                 }
830                 bglEnd();
831         
832                 /* selected uvs */
833                 UI_ThemeColor(TH_VERTEX_SELECT);
834                 glPointSize(pointsize);
835         
836                 bglBegin(GL_POINTS);
837                 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
838                         if (!BMINDEX_GET(efa))
839                                 continue;
840
841                         BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
842                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
843
844                                 if(uvedit_uv_selected(em, scene, l))
845                                         bglVertex2fv(luv->uv);
846                         }
847                 }
848                 bglEnd();       
849         }
850
851         glPointSize(1.0);
852 }
853
854 void draw_uvedit_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedit)
855 {
856         int show_uvedit, show_uvshadow;
857
858         show_uvedit= ED_space_image_show_uvedit(sima, obedit);
859         show_uvshadow= ED_space_image_show_uvshadow(sima, obedit);
860
861         if(show_uvedit || show_uvshadow) {
862                 if(show_uvshadow)
863                         draw_uvs_shadow(obedit);
864                 else
865                         draw_uvs(sima, scene, obedit);
866
867                 if(show_uvedit)
868                         drawcursor_sima(sima, ar);
869         }
870 }
871