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