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