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