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