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