Fix for bug #3802: Display problems with modifiers and uv face select
[blender.git] / source / blender / src / editface.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33
34 #include <math.h>
35 #include <string.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "BLI_blenlib.h"
40 #include "BLI_arithb.h"
41 #include "BLI_heap.h"
42 #include "BLI_edgehash.h"
43
44 #include "MTC_matrixops.h"
45
46 #include "IMB_imbuf_types.h"
47 #include "IMB_imbuf.h"
48
49 #include "DNA_image_types.h"
50 #include "DNA_mesh_types.h"
51 #include "DNA_meshdata_types.h"
52 #include "DNA_object_types.h"
53 #include "DNA_space_types.h"
54 #include "DNA_screen_types.h"
55 #include "DNA_scene_types.h"
56 #include "DNA_view3d_types.h"
57 #include "DNA_userdef_types.h"
58
59 #include "BKE_utildefines.h"
60 #include "BKE_depsgraph.h"
61 #include "BKE_displist.h"
62 #include "BKE_global.h"
63 #include "BKE_mesh.h"
64 #include "BKE_texture.h"
65 #include "BKE_object.h"
66
67 #include "BSE_view.h"
68 #include "BSE_edit.h"
69 #include "BSE_drawview.h"       /* for backdrawview3d */
70
71 #include "BIF_editsima.h"
72 #include "BIF_interface.h"
73 #include "BIF_mywindow.h"
74 #include "BIF_toolbox.h"
75 #include "BIF_screen.h"
76 #include "BIF_gl.h"
77 #include "BIF_graphics.h"
78 #include "BIF_space.h"  /* for allqueue */
79
80 #include "BDR_drawmesh.h"
81 #include "BDR_editface.h"
82 #include "BDR_vpaint.h"
83
84 #include "BDR_editface.h"
85 #include "BDR_vpaint.h"
86
87 #include "mydevice.h"
88 #include "blendef.h"
89 #include "butspace.h"
90
91 #include "../img/IMG_Api.h"
92 #include "BSE_trans_types.h"
93
94 #include "BDR_unwrapper.h"
95
96 /* returns 0 if not found, otherwise 1 */
97 static int facesel_face_pick(Mesh *me, short *mval, unsigned int *index, short rect)
98 {
99         if (!me->tface || me->totface==0)
100                 return 0;
101
102         if (G.vd->flag & V3D_NEEDBACKBUFDRAW) {
103                 check_backbuf();
104                 persp(PERSP_VIEW);
105         }
106
107         if (rect) {
108                 /* sample rect to increase changes of selecting, so that when clicking
109                    on an edge in the backbuf, we can still select a face */
110                 short dist;
111                 *index = sample_backbuf_rect(mval, 3, 1, me->totface+1, &dist);
112         }
113         else
114                 /* sample only on the exact position */
115                 *index = sample_backbuf(mval[0], mval[1]);
116
117         if ((*index)<=0 || (*index)>(unsigned int)me->totface)
118                 return 0;
119
120         (*index)--;
121         
122         return 1;
123 }
124
125 /* returns 0 if not found, otherwise 1 */
126 static int facesel_edge_pick(Mesh *me, short *mval, unsigned int *index)
127 {
128         short dist;
129         unsigned int min = me->totface + 1;
130         unsigned int max = me->totface + me->totedge + 1;
131
132         if (me->totedge == 0)
133                 return 0;
134
135         if (G.vd->flag & V3D_NEEDBACKBUFDRAW) {
136                 check_backbuf();
137                 persp(PERSP_VIEW);
138         }
139
140         *index = sample_backbuf_rect(mval, 50, min, max, &dist);
141
142         if (*index == 0)
143                 return 0;
144
145         (*index)--;
146         
147         return 1;
148 }
149
150 static void uv_calc_center_vector(float *result, Object *ob, Mesh *me)
151 {
152         float min[3], max[3], *cursx;
153         int a;
154         TFace *tface;
155         MFace *mface;
156
157         switch (G.vd->around) 
158         {
159         case V3D_CENTRE: /* bounding box center */
160                 min[0]= min[1]= min[2]= 1e20f;
161                 max[0]= max[1]= max[2]= -1e20f; 
162
163                 tface= me->tface;
164                 mface= me->mface;
165                 for(a=0; a<me->totface; a++, mface++, tface++) {
166                         if(tface->flag & TF_SELECT) {
167                                 DO_MINMAX((me->mvert+mface->v1)->co, min, max);
168                                 DO_MINMAX((me->mvert+mface->v2)->co, min, max);
169                                 DO_MINMAX((me->mvert+mface->v3)->co, min, max);
170                                 if(mface->v4) DO_MINMAX((me->mvert+mface->v4)->co, min, max);
171                         }
172                 }
173                 VecMidf(result, min, max);
174                 break;
175         case V3D_CURSOR: /*cursor center*/ 
176                 cursx= give_cursor();
177                 /* shift to objects world */
178                 result[0]= cursx[0]-ob->obmat[3][0];
179                 result[1]= cursx[1]-ob->obmat[3][1];
180                 result[2]= cursx[2]-ob->obmat[3][2];
181                 break;
182         case V3D_LOCAL: /*object center*/
183         case V3D_CENTROID: /* multiple objects centers, only one object here*/
184         default:
185                 result[0]= result[1]= result[2]= 0.0;
186                 break;
187         }
188 }
189
190 static void uv_calc_map_matrix(float result[][4], Object *ob, float upangledeg, float sideangledeg, float radius)
191 {
192         float rotup[4][4], rotside[4][4], viewmatrix[4][4], rotobj[4][4];
193         float sideangle= 0.0, upangle= 0.0;
194         int k;
195
196         /* get rotation of the current view matrix */
197         Mat4CpyMat4(viewmatrix,G.vd->viewmat);
198         /* but shifting */
199         for( k= 0; k< 4; k++) viewmatrix[3][k] =0.0;
200
201         /* get rotation of the current object matrix */
202         Mat4CpyMat4(rotobj,ob->obmat);
203         /* but shifting */
204         for( k= 0; k< 4; k++) rotobj[3][k] =0.0;
205
206         Mat4Clr(*rotup);
207         Mat4Clr(*rotside);
208
209         /* compensate front/side.. against opengl x,y,z world definition */
210         /* this is "kanonen gegen spatzen", a few plus minus 1 will do here */
211         /* i wanted to keep the reason here, so we're rotating*/
212         sideangle= M_PI * (sideangledeg + 180.0) /180.0;
213         rotside[0][0]= (float)cos(sideangle);
214         rotside[0][1]= -(float)sin(sideangle);
215         rotside[1][0]= (float)sin(sideangle);
216         rotside[1][1]= (float)cos(sideangle);
217         rotside[2][2]= 1.0f;
218       
219         upangle= M_PI * upangledeg /180.0;
220         rotup[1][1]= (float)cos(upangle)/radius;
221         rotup[1][2]= -(float)sin(upangle)/radius;
222         rotup[2][1]= (float)sin(upangle)/radius;
223         rotup[2][2]= (float)cos(upangle)/radius;
224         rotup[0][0]= (float)1.0/radius;
225
226         /* calculate transforms*/
227         Mat4MulSerie(result,rotup,rotside,viewmatrix,rotobj,NULL,NULL,NULL,NULL);
228 }
229
230 static void uv_calc_shift_project(float *target, float *shift, float rotmat[][4], int projectionmode, float *source, float *min, float *max)
231 {
232         float pv[3];
233
234         VecSubf(pv, source, shift);
235         Mat4MulVecfl(rotmat, pv);
236
237         switch(projectionmode) {
238         case B_UVAUTO_CYLINDER: 
239                 tubemap(pv[0], pv[1], pv[2], &target[0],&target[1]);
240                 /* split line is always zero */
241                 if (target[0] >= 1.0f) target[0] -= 1.0f;  
242                 break;
243
244         case B_UVAUTO_SPHERE: 
245                 spheremap(pv[0], pv[1], pv[2], &target[0],&target[1]);
246                 /* split line is always zero */
247                 if (target[0] >= 1.0f) target[0] -= 1.0f;
248                 break;
249
250         case 3: /* ortho special case for BOUNDS */
251                 target[0] = -pv[0];
252                 target[1] = pv[2];
253                 break;
254
255         case 4: 
256                 {
257                 /* very special case for FROM WINDOW */
258                 float pv4[4], dx, dy, x= 0.0, y= 0.0;
259
260                 dx= G.vd->area->winx;
261                 dy= G.vd->area->winy;
262
263                 VecCopyf(pv4, source);
264         pv4[3] = 1.0;
265
266                 /* rotmat is the object matrix in this case */
267         Mat4MulVec4fl(rotmat,pv4); 
268
269                 /* almost project_short */
270             Mat4MulVec4fl(G.vd->persmat,pv4);
271                 if (fabs(pv4[3]) > 0.00001) { /* avoid division by zero */
272                         target[0] = dx/2.0 + (dx/2.0)*pv4[0]/pv4[3];
273                         target[1] = dy/2.0 + (dy/2.0)*pv4[1]/pv4[3];
274                 }
275                 else {
276                         /* scaling is lost but give a valid result */
277                         target[0] = dx/2.0 + (dx/2.0)*pv4[0];
278                         target[1] = dy/2.0 + (dy/2.0)*pv4[1];
279                 }
280
281         /* G.vd->persmat seems to do this funky scaling */ 
282                 if(dx > dy) {
283                         y= (dx-dy)/2.0;
284                         dy = dx;
285                 }
286                 else {
287                         x= (dy-dx)/2.0;
288                         dx = dy;
289                 }
290                 target[0]= (x + target[0])/dx;
291                 target[1]= (y + target[1])/dy;
292
293                 }
294                 break;
295
296     default:
297                 target[0] = 0.0;
298                 target[1] = 1.0;
299         }
300
301         /* we know the values here and may need min_max later */
302         /* max requests independand from min; not fastest but safest */ 
303         if(min) {
304                 min[0] = MIN2(target[0], min[0]);
305                 min[1] = MIN2(target[1], min[1]);
306         }
307         if(max) {
308                 max[0] = MAX2(target[0], max[0]);
309                 max[1] = MAX2(target[1], max[1]);
310         }
311 }
312
313 void calculate_uv_map(unsigned short mapmode)
314 {
315         Mesh *me;
316         TFace *tface;
317         MFace *mface;
318         Object *ob;
319         float dx, dy, rotatematrix[4][4], radius= 1.0, min[3], cent[3], max[3];
320         float fac= 1.0, upangledeg= 0.0, sideangledeg= 90.0;
321         int i, b, mi, a, n;
322
323         if(G.scene->toolsettings->uvcalc_mapdir==1)  {
324                 upangledeg= 90.0;
325                 sideangledeg= 0.0;
326         }
327         else {
328                 upangledeg= 0.0;
329                 if(G.scene->toolsettings->uvcalc_mapalign==1) sideangledeg= 0.0;
330                 else sideangledeg= 90.0;
331         }
332
333         me= get_mesh(ob=OBACT);
334         if(me==0 || me->tface==0) return;
335         if(me->totface==0) return;
336         
337         switch(mapmode) {
338         case B_UVAUTO_BOUNDS1:
339         case B_UVAUTO_BOUNDS2:
340         case B_UVAUTO_BOUNDS4:
341         case B_UVAUTO_BOUNDS8:
342                 switch(mapmode) {
343                 case B_UVAUTO_BOUNDS2: fac = 0.5; break;
344                 case B_UVAUTO_BOUNDS4: fac = 0.25; break;
345                 case B_UVAUTO_BOUNDS8: fac = 0.125; break;
346                 }
347
348                 min[0]= min[1]= 1.0;
349                 max[0]= max[1]= 0.0;
350
351                 uv_calc_center_vector(cent, ob, me);
352                 uv_calc_map_matrix(rotatematrix, ob, upangledeg, sideangledeg, 1.0f);
353                         
354                 tface= me->tface;
355                 mface= me->mface;
356                 for(a=0; a<me->totface; a++, mface++, tface++) {
357                         if(tface->flag & TF_SELECT) {
358                                 uv_calc_shift_project(tface->uv[0],cent,rotatematrix,3,(me->mvert+mface->v1)->co,min,max);
359                                 uv_calc_shift_project(tface->uv[1],cent,rotatematrix,3,(me->mvert+mface->v2)->co,min,max);
360                                 uv_calc_shift_project(tface->uv[2],cent,rotatematrix,3,(me->mvert+mface->v3)->co,min,max);
361                                 if(mface->v4)
362                                         uv_calc_shift_project(tface->uv[3],cent,rotatematrix,3,(me->mvert+mface->v4)->co,min,max);
363                         }
364                 }
365                 
366                 /* rescale UV to be in 0..1,1/2,1/4,1/8 */
367                 dx= (max[0]-min[0]);
368                 dy= (max[1]-min[1]);
369
370                 tface= me->tface;
371                 mface= me->mface;
372                 for(a=0; a<me->totface; a++, mface++, tface++) {
373                         if(tface->flag & TF_SELECT) {
374                                 if(mface->v4) b= 3; else b= 2;
375                                 for(; b>=0; b--) {
376                                         tface->uv[b][0]= ((tface->uv[b][0]-min[0])*fac)/dx;
377                                         tface->uv[b][1]= 1.0-fac+((tface->uv[b][1]-min[1])*fac)/dy;
378                                 }
379                         }
380                 }
381                 break;
382
383         case B_UVAUTO_WINDOW:           
384                 cent[0] = cent[1] = cent[2] = 0.0; 
385                 Mat4CpyMat4(rotatematrix,ob->obmat);
386
387                 tface= me->tface;
388                 mface= me->mface;
389                 for(a=0; a<me->totface; a++, mface++, tface++) {
390                         if(tface->flag & TF_SELECT) {
391                                 uv_calc_shift_project(tface->uv[0],cent,rotatematrix,4,(me->mvert+mface->v1)->co,NULL,NULL);
392                                 uv_calc_shift_project(tface->uv[1],cent,rotatematrix,4,(me->mvert+mface->v2)->co,NULL,NULL);
393                                 uv_calc_shift_project(tface->uv[2],cent,rotatematrix,4,(me->mvert+mface->v3)->co,NULL,NULL);
394                                 if(mface->v4)
395                                         uv_calc_shift_project(tface->uv[3],cent,rotatematrix,4,(me->mvert+mface->v4)->co,NULL,NULL);
396                         }
397                 }
398                 break;
399
400         case B_UVAUTO_STD8:
401         case B_UVAUTO_STD4:
402         case B_UVAUTO_STD2:
403         case B_UVAUTO_STD1:
404                 switch(mapmode) {
405                 case B_UVAUTO_STD8: fac = 0.125; break;
406                 case B_UVAUTO_STD4: fac = 0.25; break;
407                 case B_UVAUTO_STD2: fac = 0.5; break;
408                 }
409
410                 tface= me->tface;
411                 for(a=0; a<me->totface; a++, tface++)
412                         if(tface->flag & TF_SELECT) 
413                                 default_uv(tface->uv, fac);
414                 break;
415
416         case B_UVAUTO_CYLINDER:
417         case B_UVAUTO_SPHERE:
418                 uv_calc_center_vector(cent, ob, me);
419                         
420                 if(mapmode==B_UVAUTO_CYLINDER) radius = G.scene->toolsettings->uvcalc_radius;
421
422                 /* be compatible to the "old" sphere/cylinder mode */
423                 if (G.scene->toolsettings->uvcalc_mapdir== 2)
424                         Mat4One(rotatematrix);
425                 else 
426                         uv_calc_map_matrix(rotatematrix,ob,upangledeg,sideangledeg,radius);
427
428                 tface= me->tface;
429                 mface= me->mface;
430                 for(a=0; a<me->totface; a++, mface++, tface++) {
431                         if(tface->flag & TF_SELECT) {
432                                 uv_calc_shift_project(tface->uv[0],cent,rotatematrix,mapmode,(me->mvert+mface->v1)->co,NULL,NULL);
433                                 uv_calc_shift_project(tface->uv[1],cent,rotatematrix,mapmode,(me->mvert+mface->v2)->co,NULL,NULL);
434                                 uv_calc_shift_project(tface->uv[2],cent,rotatematrix,mapmode,(me->mvert+mface->v3)->co,NULL,NULL);
435                                 n = 3;       
436                                 if(mface->v4) {
437                                         uv_calc_shift_project(tface->uv[3],cent,rotatematrix,mapmode,(me->mvert+mface->v4)->co,NULL,NULL);
438                                         n=4;
439                                 }
440
441                                 mi = 0;
442                                 for (i = 1; i < n; i++)
443                                         if (tface->uv[i][0] > tface->uv[mi][0]) mi = i;
444
445                                 for (i = 0; i < n; i++) {
446                                         if (i != mi) {
447                                                 dx = tface->uv[mi][0] - tface->uv[i][0];
448                                                 if (dx > 0.5) tface->uv[i][0] += 1.0;
449                                         } 
450                                 } 
451                         }
452                 }
453
454                 break;
455
456         case B_UVAUTO_CUBE:
457                 {
458                 /* choose x,y,z axis for projetion depending on the largest normal */
459                 /* component, but clusters all together around the center of map */
460                 float no[3];
461                 short cox, coy;
462                 float *loc= ob->obmat[3];
463                 MVert *mv= me->mvert;
464                 float cubesize = G.scene->toolsettings->uvcalc_cubesize;
465
466                 tface= me->tface;
467                 mface= me->mface;
468                 for(a=0; a<me->totface; a++, mface++, tface++) {
469                         if(tface->flag & TF_SELECT) {
470                                 CalcNormFloat((mv+mface->v1)->co, (mv+mface->v2)->co, (mv+mface->v3)->co, no);
471                                         
472                                 no[0]= fabs(no[0]);
473                                 no[1]= fabs(no[1]);
474                                 no[2]= fabs(no[2]);
475                                 
476                                 cox=0; coy= 1;
477                                 if(no[2]>=no[0] && no[2]>=no[1]);
478                                 else if(no[1]>=no[0] && no[1]>=no[2]) coy= 2;
479                                 else { cox= 1; coy= 2; }
480                                 
481                                 tface->uv[0][0]= 0.5+0.5*cubesize*(loc[cox] + (mv+mface->v1)->co[cox]);
482                                 tface->uv[0][1]= 0.5+0.5*cubesize*(loc[coy] + (mv+mface->v1)->co[coy]);
483                                 dx = floor(tface->uv[0][0]);
484                                 dy = floor(tface->uv[0][1]);
485                                 tface->uv[0][0] -= dx;
486                                 tface->uv[0][1] -= dy;
487                                 tface->uv[1][0]= 0.5+0.5*cubesize*(loc[cox] + (mv+mface->v2)->co[cox]);
488                                 tface->uv[1][1]= 0.5+0.5*cubesize*(loc[coy] + (mv+mface->v2)->co[coy]);
489                                 tface->uv[1][0] -= dx;
490                                 tface->uv[1][1] -= dy;
491                                 tface->uv[2][0]= 0.5+0.5*cubesize*(loc[cox] + (mv+mface->v3)->co[cox]);
492                                 tface->uv[2][1]= 0.5+0.5*cubesize*(loc[coy] + (mv+mface->v3)->co[coy]);
493                                 tface->uv[2][0] -= dx;
494                                 tface->uv[2][1] -= dy;
495                                 if(mface->v4) {
496                                         tface->uv[3][0]= 0.5+0.5*cubesize*(loc[cox] + (mv+mface->v4)->co[cox]);
497                                         tface->uv[3][1]= 0.5+0.5*cubesize*(loc[coy] + (mv+mface->v4)->co[coy]);
498                                         tface->uv[3][0] -= dx;
499                                         tface->uv[3][1] -= dy;
500                                 }
501                         }
502                 }
503                 }
504                 break; 
505         default:
506                 return;
507         } /* end switch mapmode */
508
509         /* clipping and wrapping */
510         if(G.sima && G.sima->flag & SI_CLIP_UV) {
511                 tface= me->tface;
512                 mface= me->mface;
513                 for(a=0; a<me->totface; a++, mface++, tface++) {
514                         if(!(tface->flag & TF_SELECT)) continue;
515                                 
516                         dx= dy= 0;
517                         if(mface->v4) b= 3; else b= 2;
518                         for(; b>=0; b--) {
519                                 while(tface->uv[b][0] + dx < 0.0) dx+= 0.5;
520                                 while(tface->uv[b][0] + dx > 1.0) dx-= 0.5;
521                                 while(tface->uv[b][1] + dy < 0.0) dy+= 0.5;
522                                 while(tface->uv[b][1] + dy > 1.0) dy-= 0.5;
523                         }
524         
525                         if(mface->v4) b= 3; else b= 2;
526                         for(; b>=0; b--) {
527                                 tface->uv[b][0]+= dx;
528                                 CLAMP(tface->uv[b][0], 0.0, 1.0);
529                                 
530                                 tface->uv[b][1]+= dy;
531                                 CLAMP(tface->uv[b][1], 0.0, 1.0);
532                         }
533                 }
534         }
535
536         BIF_undo_push("UV calculation");
537
538         object_uvs_changed(OBACT);
539
540         allqueue(REDRAWVIEW3D, 0);
541         allqueue(REDRAWIMAGE, 0);
542 }
543
544 TFace *get_active_tface()
545 {
546         Mesh *me;
547         TFace *tf;
548         int a;
549         
550         if(OBACT==NULL || OBACT->type!=OB_MESH)
551                 return NULL;
552         
553         me= get_mesh(OBACT);
554         if(me==0 || me->tface==0)
555                 return NULL;
556         
557         for(a=0, tf=me->tface; a < me->totface; a++, tf++)
558                 if(tf->flag & TF_ACTIVE)
559                         return tf;
560
561         for(a=0, tf=me->tface; a < me->totface; a++, tf++)
562                 if(tf->flag & TF_SELECT)
563                         return tf;
564
565         for(a=0, tf=me->tface; a < me->totface; a++, tf++)
566                 if((tf->flag & TF_HIDE)==0)
567                         return tf;
568         
569         return NULL;
570 }
571
572 void default_uv(float uv[][2], float size)
573 {
574         int dy;
575         
576         if(size>1.0) size= 1.0;
577
578         dy= 1.0-size;
579         
580         uv[0][0]= 0;
581         uv[0][1]= size+dy;
582         
583         uv[1][0]= 0;
584         uv[1][1]= dy;
585         
586         uv[2][0]= size;
587         uv[2][1]= dy;
588         
589         uv[3][0]= size;
590         uv[3][1]= size+dy;
591         
592         
593 }
594
595 void default_tface(TFace *tface)
596 {
597         default_uv(tface->uv, 1.0);
598
599         tface->col[0]= tface->col[1]= tface->col[2]= tface->col[3]= vpaint_get_current_col();
600
601         tface->mode= TF_TEX;
602         tface->mode= 0;
603         tface->flag= TF_SELECT;
604         tface->tpage= 0;
605         tface->mode |= TF_DYNAMIC;
606 }
607
608 void make_tfaces(Mesh *me) 
609 {
610         TFace *tface;
611         int a;
612         
613         a= me->totface;
614         if(a==0) return;
615         tface= me->tface= MEM_callocN(a*sizeof(TFace), "tface");
616         while(a--) {
617                 default_tface(tface);
618                 tface++;
619         }
620         if(me->mcol) {
621                 mcol_to_tface(me, 1);
622         }
623 }
624
625
626 void reveal_tface()
627 {
628         Mesh *me;
629         TFace *tface;
630         int a;
631         
632         me= get_mesh(OBACT);
633         if(me==0 || me->tface==0 || me->totface==0) return;
634         
635         tface= me->tface;
636         a= me->totface;
637         while(a--) {
638                 if(tface->flag & TF_HIDE) {
639                         tface->flag |= TF_SELECT;
640                         tface->flag -= TF_HIDE;
641                 }
642                 tface++;
643         }
644
645         BIF_undo_push("Reveal UV face");
646
647         object_tface_flags_changed(OBACT, 0);
648 }
649
650 void hide_tface()
651 {
652         Mesh *me;
653         TFace *tface;
654         int a;
655         
656         me= get_mesh(OBACT);
657         if(me==0 || me->tface==0 || me->totface==0) return;
658         
659         if(G.qual & LR_ALTKEY) {
660                 reveal_tface();
661                 return;
662         }
663         
664         tface= me->tface;
665         a= me->totface;
666         while(a--) {
667                 if(tface->flag & TF_HIDE);
668                 else {
669                         if(G.qual & LR_SHIFTKEY) {
670                                 if( (tface->flag & TF_SELECT)==0) tface->flag |= TF_HIDE;
671                         }
672                         else {
673                                 if( (tface->flag & TF_SELECT)) tface->flag |= TF_HIDE;
674                         }
675                 }
676                 if(tface->flag & TF_HIDE) tface->flag &= ~TF_SELECT;
677                 
678                 tface++;
679         }
680
681         BIF_undo_push("Hide UV face");
682
683         object_tface_flags_changed(OBACT, 0);
684 }
685
686 void select_linked_tfaces(int mode)
687 {
688         Object *ob;
689         Mesh *me;
690         short mval[2];
691         unsigned int index=0;
692
693         ob = OBACT;
694         me = get_mesh(ob);
695         if(me==0 || me->tface==0 || me->totface==0) return;
696
697         if (mode==0 || mode==1) {
698                 if (!(ob->lay & G.vd->lay))
699                         error("The active object is not in this layer");
700                         
701                 getmouseco_areawin(mval);
702                 if (!facesel_face_pick(me, mval, &index, 1)) return;
703         }
704
705         select_linked_tfaces_with_seams(mode, me, index);
706 }
707
708 void deselectall_tface()
709 {
710         Mesh *me;
711         TFace *tface;
712         int a, sel;
713                 
714         me= get_mesh(OBACT);
715         if(me==0 || me->tface==0) return;
716         
717         tface= me->tface;
718         a= me->totface;
719         sel= 0;
720         while(a--) {
721                 if(tface->flag & TF_HIDE);
722                 else if(tface->flag & TF_SELECT) sel= 1;
723                 tface++;
724         }
725         
726         tface= me->tface;
727         a= me->totface;
728         while(a--) {
729                 if(tface->flag & TF_HIDE);
730                 else {
731                         if(sel) tface->flag &= ~TF_SELECT;
732                         else tface->flag |= TF_SELECT;
733                 }
734                 tface++;
735         }
736
737         BIF_undo_push("(De)select all UV face");
738
739         object_tface_flags_changed(OBACT, 0);
740 }
741
742 void selectswap_tface(void)
743 {
744         Mesh *me;
745         TFace *tface;
746         int a;
747                 
748         me= get_mesh(OBACT);
749         if(me==0 || me->tface==0) return;
750         
751         tface= me->tface;
752         a= me->totface;
753         while(a--) {
754                 if(tface->flag & TF_HIDE);
755                 else {
756                         if(tface->flag & TF_SELECT) tface->flag &= ~TF_SELECT;
757                         else tface->flag |= TF_SELECT;
758                 }
759                 tface++;
760         }
761
762         BIF_undo_push("Select inverse UV face");
763
764         object_tface_flags_changed(OBACT, 0);
765 }
766
767 void rotate_uv_tface()
768 {
769         Mesh *me;
770         TFace *tface;
771         MFace *mface;
772         short mode;
773         int a;
774         
775         me= get_mesh(OBACT);
776         if(me==0 || me->tface==0) return;
777         
778         mode= pupmenu("Rotate %t|UV Co-ordinates %x1|Vertex Colors %x2");
779         
780         if(mode<1) return;
781         
782         tface= me->tface;
783         mface= me->mface;
784         a= me->totface;
785         while(a--) {
786                 if(tface->flag & TF_SELECT) {
787                         if(mode==1) {
788                                 float u1= tface->uv[0][0];
789                                 float v1= tface->uv[0][1];
790                                 
791                                 tface->uv[0][0]= tface->uv[1][0];
792                                 tface->uv[0][1]= tface->uv[1][1];
793         
794                                 tface->uv[1][0]= tface->uv[2][0];
795                                 tface->uv[1][1]= tface->uv[2][1];
796         
797                                 if(mface->v4) {
798                                         tface->uv[2][0]= tface->uv[3][0];
799                                         tface->uv[2][1]= tface->uv[3][1];
800                                 
801                                         tface->uv[3][0]= u1;
802                                         tface->uv[3][1]= v1;
803                                 }
804                                 else {
805                                         tface->uv[2][0]= u1;
806                                         tface->uv[2][1]= v1;
807                                 }
808                         }
809                         else if(mode==2) {
810                                 unsigned int tcol= tface->col[0];
811                                 
812                                 tface->col[0]= tface->col[1];
813                                 tface->col[1]= tface->col[2];
814         
815                                 if(mface->v4) {
816                                         tface->col[2]= tface->col[3];
817                                         tface->col[3]= tcol;
818                                 }
819                                 else {
820                                         tface->col[2]= tcol;
821                                 }
822                         }
823                 }
824                 tface++;
825                 mface++;
826         }
827         
828         BIF_undo_push("Rotate UV face");
829
830         object_uvs_changed(OBACT);
831 }
832
833 void mirror_uv_tface()
834 {
835         Mesh *me;
836         TFace *tface;
837         MFace *mface;
838         short mode;
839         int a;
840         
841         me= get_mesh(OBACT);
842         if(me==0 || me->tface==0) return;
843         
844         mode= pupmenu("Mirror %t|UV Co-ordinates %x1|Vertex Colors %x2");
845         
846         if(mode<1) return;
847         
848         tface= me->tface;
849         mface= me->mface;
850         a= me->totface;
851         while(a--) {
852                 if(tface->flag & TF_SELECT) {
853                         if(mode==1) {
854                                 float u1= tface->uv[0][0];
855                                 float v1= tface->uv[0][1];
856                                 if(mface->v4) {
857                                         tface->uv[0][0]= tface->uv[3][0];
858                                         tface->uv[0][1]= tface->uv[3][1];
859                                 
860                                         tface->uv[3][0]= u1;
861                                         tface->uv[3][1]= v1;
862
863                                         u1= tface->uv[1][0];
864                                         v1= tface->uv[1][1];
865
866                                         tface->uv[1][0]= tface->uv[2][0];
867                                         tface->uv[1][1]= tface->uv[2][1];
868                                 
869                                         tface->uv[2][0]= u1;
870                                         tface->uv[2][1]= v1;
871                                 }
872                                 else {
873                                         tface->uv[0][0]= tface->uv[2][0];
874                                         tface->uv[0][1]= tface->uv[2][1];
875                                         tface->uv[2][0]= u1;
876                                         tface->uv[2][1]= v1;
877                                 }
878                         }
879                         else if(mode==2) {
880                                 unsigned int tcol= tface->col[0];
881                                 if(mface->v4) {
882                                         tface->col[0]= tface->col[3];
883                                         tface->col[3]= tcol;
884
885                                         tcol = tface->col[1];
886                                         tface->col[1]= tface->col[2];
887                                         tface->col[2]= tcol;
888                                 }
889                                 else {
890                                         tface->col[0]= tface->col[2];
891                                         tface->col[2]= tcol;
892                                 }
893                         }
894                 }
895                 tface++;
896                 mface++;
897         }
898         
899         BIF_undo_push("Mirror UV face");
900
901         object_uvs_changed(OBACT);
902 }
903
904 void minmax_tface(float *min, float *max)
905 {
906         Object *ob;
907         Mesh *me;
908         MFace *mf;
909         TFace *tf;
910         MVert *mv;
911         int a;
912         float vec[3], bmat[3][3];
913         
914         ob = OBACT;
915         if (ob==0) return;
916         me= get_mesh(ob);
917         if(me==0 || me->tface==0) return;
918         
919         Mat3CpyMat4(bmat, ob->obmat);
920
921         mv= me->mvert;
922         mf= me->mface;
923         tf= me->tface;
924         for (a=me->totface; a>0; a--, mf++, tf++) {
925                 if (tf->flag & TF_HIDE || !(tf->flag & TF_SELECT))
926                         continue;
927
928                 VECCOPY(vec, (mv+mf->v1)->co);
929                 Mat3MulVecfl(bmat, vec);
930                 VecAddf(vec, vec, ob->obmat[3]);
931                 DO_MINMAX(vec, min, max);               
932
933                 VECCOPY(vec, (mv+mf->v2)->co);
934                 Mat3MulVecfl(bmat, vec);
935                 VecAddf(vec, vec, ob->obmat[3]);
936                 DO_MINMAX(vec, min, max);               
937
938                 VECCOPY(vec, (mv+mf->v3)->co);
939                 Mat3MulVecfl(bmat, vec);
940                 VecAddf(vec, vec, ob->obmat[3]);
941                 DO_MINMAX(vec, min, max);               
942
943                 if (mf->v4) {
944                         VECCOPY(vec, (mv+mf->v4)->co);
945                         Mat3MulVecfl(bmat, vec);
946                         VecAddf(vec, vec, ob->obmat[3]);
947                         DO_MINMAX(vec, min, max);
948                 }
949         }
950 }
951
952 #define ME_SEAM_DONE ME_SEAM_LAST               /* reuse this flag */
953
954 static float seam_cut_cost(Mesh *me, int e1, int e2, int vert)
955 {
956         MVert *v = me->mvert + vert;
957         MEdge *med1 = me->medge + e1, *med2 = me->medge + e2;
958         MVert *v1 = me->mvert + ((med1->v1 == vert)? med1->v2: med1->v1);
959         MVert *v2 = me->mvert + ((med2->v1 == vert)? med2->v2: med2->v1);
960         float cost, d1[3], d2[3];
961
962         cost = VecLenf(v1->co, v->co);
963         cost += VecLenf(v->co, v2->co);
964
965         VecSubf(d1, v->co, v1->co);
966         VecSubf(d2, v2->co, v->co);
967
968         cost = cost + 0.5f*cost*(2.0f - fabs(d1[0]*d2[0] + d1[1]*d2[1] + d1[2]*d2[2]));
969
970         return cost;
971 }
972
973 static void seam_add_adjacent(Mesh *me, Heap *heap, int mednum, int vertnum, int *nedges, int *edges, int *prevedge, float *cost)
974 {
975         int startadj, endadj = nedges[vertnum+1];
976
977         for (startadj = nedges[vertnum]; startadj < endadj; startadj++) {
978                 int adjnum = edges[startadj];
979                 MEdge *medadj = me->medge + adjnum;
980                 float newcost;
981
982                 if (medadj->flag & ME_SEAM_DONE)
983                         continue;
984
985                 newcost = cost[mednum] + seam_cut_cost(me, mednum, adjnum, vertnum);
986
987                 if (cost[adjnum] > newcost) {
988                         cost[adjnum] = newcost;
989                         prevedge[adjnum] = mednum;
990                         BLI_heap_insert(heap, newcost, (void*)adjnum);
991                 }
992         }
993 }
994
995 static int seam_shortest_path(Mesh *me, int source, int target)
996 {
997         Heap *heap;
998         EdgeHash *ehash;
999         float *cost;
1000         MEdge *med;
1001         int a, *nedges, *edges, *prevedge, mednum = -1, nedgeswap = 0;
1002         TFace *tf;
1003         MFace *mf;
1004
1005         /* mark hidden edges as done, so we don't use them */
1006         ehash = BLI_edgehash_new();
1007
1008         for (a=0, mf=me->mface, tf=me->tface; a<me->totface; a++, tf++, mf++) {
1009                 if (!(tf->flag & TF_HIDE)) {
1010                         BLI_edgehash_insert(ehash, mf->v1, mf->v2, NULL);
1011                         BLI_edgehash_insert(ehash, mf->v2, mf->v3, NULL);
1012                         if (mf->v4) {
1013                                 BLI_edgehash_insert(ehash, mf->v3, mf->v4, NULL);
1014                                 BLI_edgehash_insert(ehash, mf->v4, mf->v1, NULL);
1015                         }
1016                         else
1017                                 BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL);
1018                 }
1019         }
1020
1021         for (a=0, med=me->medge; a<me->totedge; a++, med++)
1022                 if (!BLI_edgehash_haskey(ehash, med->v1, med->v2))
1023                         med->flag |= ME_SEAM_DONE;
1024
1025         BLI_edgehash_free(ehash, NULL);
1026
1027         /* alloc */
1028         nedges = MEM_callocN(sizeof(*nedges)*me->totvert+1, "SeamPathNEdges");
1029         edges = MEM_mallocN(sizeof(*edges)*me->totedge*2, "SeamPathEdges");
1030         prevedge = MEM_mallocN(sizeof(*prevedge)*me->totedge, "SeamPathPrevious");
1031         cost = MEM_mallocN(sizeof(*cost)*me->totedge, "SeamPathCost");
1032
1033         /* count edges, compute adjacent edges offsets and fill adjacent edges */
1034         for (a=0, med=me->medge; a<me->totedge; a++, med++) {
1035                 nedges[med->v1+1]++;
1036                 nedges[med->v2+1]++;
1037         }
1038
1039         for (a=1; a<me->totvert; a++) {
1040                 int newswap = nedges[a+1];
1041                 nedges[a+1] = nedgeswap + nedges[a];
1042                 nedgeswap = newswap;
1043         }
1044         nedges[0] = nedges[1] = 0;
1045
1046         for (a=0, med=me->medge; a<me->totedge; a++, med++) {
1047                 edges[nedges[med->v1+1]++] = a;
1048                 edges[nedges[med->v2+1]++] = a;
1049
1050                 cost[a] = 1e20f;
1051                 prevedge[a] = -1;
1052         }
1053
1054         /* regular dijkstra shortest path, but over edges instead of vertices */
1055         heap = BLI_heap_new();
1056         BLI_heap_insert(heap, 0.0f, (void*)source);
1057         cost[source] = 0.0f;
1058
1059         while (!BLI_heap_empty(heap)) {
1060                 mednum = (int)BLI_heap_popmin(heap);
1061                 med = me->medge + mednum;
1062
1063                 if (mednum == target)
1064                         break;
1065
1066                 if (med->flag & ME_SEAM_DONE)
1067                         continue;
1068
1069                 med->flag |= ME_SEAM_DONE;
1070
1071                 seam_add_adjacent(me, heap, mednum, med->v1, nedges, edges, prevedge, cost);
1072                 seam_add_adjacent(me, heap, mednum, med->v2, nedges, edges, prevedge, cost);
1073         }
1074         
1075         MEM_freeN(nedges);
1076         MEM_freeN(edges);
1077         MEM_freeN(cost);
1078         BLI_heap_free(heap, NULL);
1079
1080         for (a=0, med=me->medge; a<me->totedge; a++, med++)
1081                 med->flag &= ~ME_SEAM_DONE;
1082
1083         if (mednum != target) {
1084                 MEM_freeN(prevedge);
1085                 return 0;
1086         }
1087
1088         /* follow path back to source and mark as seam */
1089         if (mednum == target) {
1090                 short allseams = 1;
1091
1092                 mednum = target;
1093                 do {
1094                         med = me->medge + mednum;
1095                         if (!(med->flag & ME_SEAM)) {
1096                                 allseams = 0;
1097                                 break;
1098                         }
1099                         mednum = prevedge[mednum];
1100                 } while (mednum != source);
1101
1102                 mednum = target;
1103                 do {
1104                         med = me->medge + mednum;
1105                         if (allseams)
1106                                 med->flag &= ~ME_SEAM;
1107                         else
1108                                 med->flag |= ME_SEAM;
1109                         mednum = prevedge[mednum];
1110                 } while (mednum != -1);
1111         }
1112
1113         MEM_freeN(prevedge);
1114         return 1;
1115 }
1116
1117 static void seam_select(Mesh *me, short *mval, short path)
1118 {
1119         unsigned int index = 0;
1120         MEdge *medge, *med;
1121         int a, lastindex = -1;
1122
1123         if (!facesel_edge_pick(me, mval, &index))
1124                 return;
1125
1126         for (a=0, med=me->medge; a<me->totedge; a++, med++) {
1127                 if (med->flag & ME_SEAM_LAST) {
1128                         lastindex = a;
1129                         med->flag &= ~ME_SEAM_LAST;
1130                         break;
1131                 }
1132         }
1133
1134         medge = me->medge + index;
1135         if (!path || (lastindex == -1) || (index == lastindex) ||
1136             !seam_shortest_path(me, lastindex, index))
1137                 medge->flag ^= ME_SEAM;
1138         medge->flag |= ME_SEAM_LAST;
1139
1140         G.f |= G_DRAWSEAMS;
1141
1142         if (G.rt == 8)
1143                 unwrap_lscm(1);
1144
1145         BIF_undo_push("Mark Seam");
1146
1147         object_tface_flags_changed(OBACT, 1);
1148 }
1149
1150 void seam_edgehash_insert_face(EdgeHash *ehash, MFace *mf)
1151 {
1152         BLI_edgehash_insert(ehash, mf->v1, mf->v2, NULL);
1153         BLI_edgehash_insert(ehash, mf->v2, mf->v3, NULL);
1154         if (mf->v4) {
1155                 BLI_edgehash_insert(ehash, mf->v3, mf->v4, NULL);
1156                 BLI_edgehash_insert(ehash, mf->v4, mf->v1, NULL);
1157         }
1158         else
1159                 BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL);
1160 }
1161
1162 void seam_mark_clear_tface(short mode)
1163 {
1164         Mesh *me;
1165         TFace *tf;
1166         MFace *mf;
1167         MEdge *med;
1168         int a;
1169         
1170         me= get_mesh(OBACT);
1171         if(me==0 || me->tface==0 || me->totface==0) return;
1172
1173         if (mode == 0)
1174                 mode = pupmenu("Seams%t|Mark Border Seam %x1|Clear Seam %x2");
1175
1176         if (mode != 1 && mode != 2)
1177                 return;
1178
1179         if (mode == 2) {
1180                 EdgeHash *ehash = BLI_edgehash_new();
1181
1182                 for (a=0, mf=me->mface, tf=me->tface; a<me->totface; a++, tf++, mf++)
1183                         if (!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT))
1184                                 seam_edgehash_insert_face(ehash, mf);
1185
1186                 for (a=0, med=me->medge; a<me->totedge; a++, med++)
1187                         if (BLI_edgehash_haskey(ehash, med->v1, med->v2))
1188                                 med->flag &= ~ME_SEAM;
1189
1190                 BLI_edgehash_free(ehash, NULL);
1191         }
1192         else {
1193                 /* mark edges that are on both selected and deselected faces */
1194                 EdgeHash *ehash1 = BLI_edgehash_new();
1195                 EdgeHash *ehash2 = BLI_edgehash_new();
1196
1197                 for (a=0, mf=me->mface, tf=me->tface; a<me->totface; a++, tf++, mf++) {
1198                         if ((tf->flag & TF_HIDE) || !(tf->flag & TF_SELECT))
1199                                 seam_edgehash_insert_face(ehash1, mf);
1200                         else
1201                                 seam_edgehash_insert_face(ehash2, mf);
1202                 }
1203
1204                 for (a=0, med=me->medge; a<me->totedge; a++, med++)
1205                         if (BLI_edgehash_haskey(ehash1, med->v1, med->v2) &&
1206                             BLI_edgehash_haskey(ehash2, med->v1, med->v2))
1207                                 med->flag |= ME_SEAM;
1208
1209                 BLI_edgehash_free(ehash1, NULL);
1210                 BLI_edgehash_free(ehash2, NULL);
1211         }
1212
1213         if (G.rt == 8)
1214                 unwrap_lscm(1);
1215
1216         G.f |= G_DRAWSEAMS;
1217         BIF_undo_push("Mark Seam");
1218
1219         object_tface_flags_changed(OBACT, 1);
1220 }
1221
1222 void face_select()
1223 {
1224         Object *ob;
1225         Mesh *me;
1226         TFace *tface, *tsel;
1227         MFace *msel;
1228         short mval[2];
1229         unsigned int a, index;
1230
1231         /* Get the face under the cursor */
1232         ob = OBACT;
1233         if (!(ob->lay & G.vd->lay)) {
1234                 error("The active object is not in this layer");
1235         }
1236         me = get_mesh(ob);
1237         getmouseco_areawin(mval);
1238
1239         if (G.qual & LR_ALTKEY) {
1240                 seam_select(me, mval, (G.qual & LR_SHIFTKEY) != 0);
1241                 return;
1242         }
1243
1244         if (!facesel_face_pick(me, mval, &index, 1)) return;
1245         
1246         tsel= (((TFace*)me->tface)+index);
1247         msel= (((MFace*)me->mface)+index);
1248
1249         if (tsel->flag & TF_HIDE) return;
1250         
1251         /* clear flags */
1252         tface = me->tface;
1253         a = me->totface;
1254         while (a--) {
1255                 if (G.qual & LR_SHIFTKEY)
1256                         tface->flag &= ~TF_ACTIVE;
1257                 else
1258                         tface->flag &= ~(TF_ACTIVE+TF_SELECT);
1259                 tface++;
1260         }
1261         
1262         tsel->flag |= TF_ACTIVE;
1263
1264         if (G.qual & LR_SHIFTKEY) {
1265                 if (tsel->flag & TF_SELECT)
1266                         tsel->flag &= ~TF_SELECT;
1267                 else
1268                         tsel->flag |= TF_SELECT;
1269         }
1270         else tsel->flag |= TF_SELECT;
1271         
1272         /* image window redraw */
1273         
1274         BIF_undo_push("Select UV face");
1275
1276         object_tface_flags_changed(OBACT, 1);
1277 }
1278
1279 void face_borderselect()
1280 {
1281         Mesh *me;
1282         TFace *tface;
1283         rcti rect;
1284         struct ImBuf *ibuf;
1285         unsigned int *rt;
1286         int a, sx, sy, index, val;
1287         char *selar;
1288         
1289         me= get_mesh(OBACT);
1290         if(me==0 || me->tface==0) return;
1291         if(me->totface==0) return;
1292         
1293         val= get_border(&rect, 3);
1294         
1295         /* why readbuffer here? shouldn't be necessary (maybe a flush or so) */
1296         glReadBuffer(GL_BACK);
1297 #ifdef __APPLE__
1298         glReadBuffer(GL_AUX0); /* apple only */
1299 #endif
1300         
1301         if(val) {
1302                 selar= MEM_callocN(me->totface+1, "selar");
1303                 
1304                 sx= (rect.xmax-rect.xmin+1);
1305                 sy= (rect.ymax-rect.ymin+1);
1306                 if(sx*sy<=0) return;
1307
1308                 ibuf = IMB_allocImBuf(sx,sy,32,IB_rect,0);
1309                 rt = ibuf->rect;
1310                 glReadPixels(rect.xmin+curarea->winrct.xmin,  rect.ymin+curarea->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE,  ibuf->rect);
1311                 if(G.order==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
1312
1313                 a= sx*sy;
1314                 while(a--) {
1315                         if(*rt) {
1316                                 index= framebuffer_to_index(*rt);
1317                                 if(index<=me->totface) selar[index]= 1;
1318                         }
1319                         rt++;
1320                 }
1321                 
1322                 tface= me->tface;
1323                 for(a=1; a<=me->totface; a++, tface++) {
1324                         if(selar[a]) {
1325                                 if(tface->flag & TF_HIDE);
1326                                 else {
1327                                         if(val==LEFTMOUSE) tface->flag |= TF_SELECT;
1328                                         else tface->flag &= ~TF_SELECT;
1329                                 }
1330                         }
1331                 }
1332                 
1333                 IMB_freeImBuf(ibuf);
1334                 MEM_freeN(selar);
1335
1336                 BIF_undo_push("Border Select UV face");
1337
1338                 object_tface_flags_changed(OBACT, 0);
1339         }
1340 #ifdef __APPLE__        
1341         glReadBuffer(GL_BACK);
1342 #endif
1343 }
1344
1345 /* Pupmenu codes: */
1346 #define UV_CUBE_MAPPING 2
1347 #define UV_CYL_MAPPING 3
1348 #define UV_SPHERE_MAPPING 4
1349 #define UV_BOUNDS8_MAPPING 68
1350 #define UV_BOUNDS4_MAPPING 65
1351 #define UV_BOUNDS2_MAPPING 66
1352 #define UV_BOUNDS1_MAPPING 67
1353 #define UV_STD8_MAPPING 131
1354 #define UV_STD4_MAPPING 130
1355 #define UV_STD2_MAPPING 129
1356 #define UV_STD1_MAPPING 128
1357 #define UV_WINDOW_MAPPING 5
1358 #define UV_UNWRAP_MAPPING 6
1359 #define UV_CYL_EX 32
1360 #define UV_SPHERE_EX 34
1361
1362 /* Some macro tricks to make pupmenu construction look nicer :-)
1363    Sorry, just did it for fun. */
1364
1365 #define _STR(x) " " #x
1366 #define STRING(x) _STR(x)
1367
1368 #define MENUSTRING(string, code) string " %x" STRING(code)
1369 #define MENUTITLE(string) string " %t|" 
1370
1371 void uv_autocalc_tface()
1372 {
1373         short mode;
1374         mode= pupmenu(MENUTITLE("UV Calculation")
1375                       MENUSTRING("Cube",          UV_CUBE_MAPPING) "|"
1376                       MENUSTRING("Cylinder",      UV_CYL_MAPPING) "|"
1377                       MENUSTRING("Sphere",        UV_SPHERE_MAPPING) "|"
1378                       MENUSTRING("Unwrap",          UV_UNWRAP_MAPPING) "|"
1379                       MENUSTRING("Bounds to 1/8", UV_BOUNDS8_MAPPING) "|"
1380                       MENUSTRING("Bounds to 1/4", UV_BOUNDS4_MAPPING) "|"
1381                       MENUSTRING("Bounds to 1/2", UV_BOUNDS2_MAPPING) "|"
1382                       MENUSTRING("Bounds to 1/1", UV_BOUNDS1_MAPPING) "|"
1383                       MENUSTRING("Standard 1/8",  UV_STD8_MAPPING) "|"
1384                       MENUSTRING("Standard 1/4",  UV_STD4_MAPPING) "|"
1385                       MENUSTRING("Standard 1/2",  UV_STD2_MAPPING) "|"
1386                       MENUSTRING("Standard 1/1",  UV_STD1_MAPPING) "|"
1387                       MENUSTRING("From Window",   UV_WINDOW_MAPPING) );
1388         
1389         
1390         switch(mode) {
1391         case UV_CUBE_MAPPING:
1392                 calculate_uv_map(B_UVAUTO_CUBE); break;
1393         case UV_CYL_MAPPING:
1394                 calculate_uv_map(B_UVAUTO_CYLINDER); break;
1395         case UV_SPHERE_MAPPING:
1396                 calculate_uv_map(B_UVAUTO_SPHERE); break;
1397         case UV_BOUNDS8_MAPPING:
1398                 calculate_uv_map(B_UVAUTO_BOUNDS8); break;
1399         case UV_BOUNDS4_MAPPING:
1400                 calculate_uv_map(B_UVAUTO_BOUNDS4); break;
1401         case UV_BOUNDS2_MAPPING:
1402                 calculate_uv_map(B_UVAUTO_BOUNDS2); break;
1403         case UV_BOUNDS1_MAPPING:
1404                 calculate_uv_map(B_UVAUTO_BOUNDS1); break;
1405         case UV_STD8_MAPPING:
1406                 calculate_uv_map(B_UVAUTO_STD8); break;
1407         case UV_STD4_MAPPING:
1408                 calculate_uv_map(B_UVAUTO_STD4); break;
1409         case UV_STD2_MAPPING:
1410                 calculate_uv_map(B_UVAUTO_STD2); break;
1411         case UV_STD1_MAPPING:
1412                 calculate_uv_map(B_UVAUTO_STD1); break;
1413         case UV_WINDOW_MAPPING:
1414                 calculate_uv_map(B_UVAUTO_WINDOW); break;
1415         case UV_UNWRAP_MAPPING:
1416                 unwrap_lscm(0); break;
1417         }
1418 }
1419
1420 void set_faceselect()   /* toggle */
1421 {
1422         Object *ob = OBACT;
1423         Mesh *me = 0;
1424         
1425         scrarea_queue_headredraw(curarea);
1426         if(ob==NULL) return;
1427         if(ob->id.lib) {
1428                 error("Can't edit library data");
1429                 return;
1430         }
1431
1432         me= get_mesh(ob);
1433         if(me && me->id.lib) {
1434                 error("Can't edit library data");
1435                 return;
1436         }
1437         
1438         if(me) /* make sure modifiers are updated for mapping requirements */
1439                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1440
1441         if(G.f & G_FACESELECT) {
1442                 G.f &= ~G_FACESELECT;
1443
1444                 if((G.f & (G_WEIGHTPAINT|G_VERTEXPAINT|G_TEXTUREPAINT))==0) {
1445                         if(me)
1446                                 reveal_tface();
1447                         setcursor_space(SPACE_VIEW3D, CURSOR_STD);
1448                         BIF_undo_push("End UV Faceselect");
1449                 }
1450         }
1451         else if (me) {
1452                 G.f |= G_FACESELECT;
1453                 if(me->tface==NULL)
1454                         make_tfaces(me);
1455
1456                 setcursor_space(SPACE_VIEW3D, CURSOR_FACESEL);
1457                 BIF_undo_push("Set UV Faceselect");
1458         }
1459
1460         countall();
1461
1462         allqueue(REDRAWVIEW3D, 0);
1463         allqueue(REDRAWBUTSEDIT, 0);
1464         allqueue(REDRAWIMAGE, 0);
1465 }
1466
1467 void set_texturepaint() /* toggle */
1468 {
1469         Object *ob = OBACT;
1470         Mesh *me = 0;
1471         
1472         scrarea_queue_headredraw(curarea);
1473         if(ob==NULL) return;
1474         if(ob->id.lib) {
1475                 error("Can't edit library data");
1476                 return;
1477         }
1478
1479         me= get_mesh(ob);
1480         if(me && me->id.lib) {
1481                 error("Can't edit library data");
1482                 return;
1483         }
1484         
1485         if(me)
1486                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1487
1488         if(G.f & G_TEXTUREPAINT)
1489                 G.f &= ~G_TEXTUREPAINT;
1490         else if (me)
1491                 G.f |= G_TEXTUREPAINT;
1492
1493         allqueue(REDRAWVIEW3D, 0);
1494 }
1495
1496 /**
1497  * Get the view ray through the screen point.
1498  * Uses the OpenGL settings of the active view port.
1499  * The coordinates should be given in viewport coordinates.
1500  * @author      Maarten Gribnau
1501  * @param       x               the x-coordinate of the screen point.
1502  * @param       y               the y-coordinate of the screen point.
1503  * @param       org             origin of the view ray.
1504  * @param       dir             direction of the view ray.
1505  */
1506 static void get_pick_ray(short x, short y, float org[3], float dir[3])
1507 {
1508         double mvmatrix[16];
1509         double projmatrix[16];
1510         GLint viewport[4];
1511         double px, py, pz;
1512         float l;
1513
1514         /* Get the matrices needed for gluUnProject */
1515         glGetIntegerv(GL_VIEWPORT, viewport);
1516         glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
1517         glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
1518
1519         /* Set up viewport so that gluUnProject will give correct values */
1520         viewport[0] = 0;
1521         viewport[1] = 0;
1522         /* printf("viewport = (%4d, %4d, %4d, %4d)\n", viewport[0], viewport[1], viewport[2], viewport[3]); */
1523         /* printf("cursor = (%4d, %4d)\n", x, y); */
1524
1525         gluUnProject((GLdouble) x, (GLdouble) y, 0.0, mvmatrix, projmatrix, viewport, &px, &py, &pz);
1526         org[0] = (float)px; org[1] = (float)py; org[2] = (float)pz;
1527         /* printf("world point at z=0.0 is (%f, %f, %f)\n", org[0], org[1], org[2]); */
1528         gluUnProject((GLdouble) x, (GLdouble) y, 1.0, mvmatrix, projmatrix, viewport, &px, &py, &pz); 
1529         /* printf("world point at z=1.0 is (%f, %f, %f)\n", px, py, pz); */
1530         dir[0] = ((float)px) - org[0];
1531         dir[1] = ((float)py) - org[1];
1532         dir[2] = ((float)pz) - org[2];
1533         l = (float)sqrt(dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]);
1534         if (!l) return;
1535         l = 1. / l;
1536         dir[0] *= l; dir[1] *= l; dir[2] *= l;
1537         /* printf("ray org. is (%f, %f, %f)\n", org[0], org[1], org[2]); */
1538         /* printf("ray dir. is (%f, %f, %f)\n", dir[0], dir[1], dir[2]); */
1539 }
1540
1541
1542 static int triangle_ray_intersect(float tv0[3], float tv1[3], float tv2[3], float org[3], float dir[3], float uv[2])
1543 {
1544         float v1v0[3];
1545         float v2v0[3];
1546         float n[3], an[3];
1547         float t, d, l;
1548         float p[3];
1549         double u0, v0, u1, v1, u2, v2, uvtemp;
1550         unsigned int iu, iv;
1551
1552         /* Calculate normal of the plane (cross, normalize)
1553          * Could really use moto here...
1554          */
1555         v1v0[0] = tv1[0] - tv0[0];
1556         v1v0[1] = tv1[1] - tv0[1];
1557         v1v0[2] = tv1[2] - tv0[2];
1558         v2v0[0] = tv2[0] - tv0[0];
1559         v2v0[1] = tv2[1] - tv0[1];
1560         v2v0[2] = tv2[2] - tv0[2];
1561         n[0] = (v1v0[1] * v2v0[2]) - (v1v0[2] * v2v0[1]);
1562         n[1] = (v1v0[2] * v2v0[0]) - (v1v0[0] * v2v0[2]);
1563         n[2] = (v1v0[0] * v2v0[1]) - (v1v0[1] * v2v0[0]);
1564         l = sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
1565         if (!l) return 0;
1566         l = 1. / l;
1567         n[0] *= l; n[1] *= l; n[2] *= l;
1568
1569         /* Calculate intersection point */
1570         t = n[0]*dir[0] + n[1]*dir[1] + n[2]*dir[2];
1571         if (fabs(t) < 1.0e-6) return 0;
1572         d = -(n[0]*tv0[0] + n[1]*tv0[1] + n[2]*tv0[2]);
1573         t = -(((n[0]*org[0] + n[1]*org[1] + n[2]*org[2]) + d) / t);
1574         if (t < 0) return 0;
1575         p[0] = org[0] + dir[0]*t;
1576         p[1] = org[1] + dir[1]*t;
1577         p[2] = org[2] + dir[2]*t;
1578         /*printf("intersection at (%f, %f, %f)\n", p[0], p[1], p[2]);*/
1579
1580         /* Calculate the largest component of the normal */
1581         an[0] = fabs(n[0]); an[1] = fabs(n[1]); an[2] = fabs(n[2]);
1582         if ((an[0] > an[1]) && (an[0] > an[2])) {
1583                 iu = 1; iv = 2;
1584         }
1585         else if ((an[1] > an[0]) && (an[1] > an[2])) {
1586                 iu = 2; iv = 0;
1587         }
1588         else {
1589                 iu = 0; iv = 1;
1590         }
1591         /* printf("iu, iv = (%d, %d)\n", iu, iv); */
1592
1593         /* Calculate (u,v) */
1594         u0 = p[iu] - tv0[iu];
1595         v0 = p[iv] - tv0[iv];
1596         u1 = tv1[iu] - tv0[iu];
1597         v1 = tv1[iv] - tv0[iv];
1598         u2 = tv2[iu] - tv0[iu];
1599         v2 = tv2[iv] - tv0[iv];
1600         /* printf("u0, v0, u1, v1, u2, v2 = (%f, %f, %f, %f, %f, %f)\n", u0, v0, u1, v1, u2, v2); */
1601
1602         /* These calculations should be in double precision.
1603          * On windows we get inpredictable results in single precision
1604          */
1605         if (u1 == 0) {
1606                 uvtemp = u0/u2;
1607                 uv[1] = (float)uvtemp;
1608                 /* if ((uv[1] >= 0.) && (uv[1] <= 1.)) { */
1609                         uv[0] = (float)((v0 - uvtemp*v2) / v1);
1610                 /* } */
1611         }
1612         else {
1613                 uvtemp = (v0*u1 - u0*v1)/(v2*u1-u2*v1);
1614                 uv[1] = (float)uvtemp;
1615                 /* if ((uv[1] >= 0) && (uv[1] <= 1)) { */
1616                         uv[0] = (float)((u0 - uvtemp*u2) / u1);
1617                 /* } */
1618         }
1619         /* printf("uv[0], uv[1] = (%f, %f)\n", uv[0], uv[1]); */
1620         return ((uv[0] >= 0) && (uv[1] >= 0) && ((uv[0]+uv[1]) <= 1)) ? 2 : 1;
1621 }
1622
1623 /**
1624  * Returns the vertex (local) coordinates of a face.
1625  * No bounds checking!
1626  * @author      Maarten Gribnau
1627  * @param       mesh    the mesh with the face.
1628  * @param       face    the face.
1629  * @param       v1              vertex 1 coordinates.
1630  * @param       v2              vertex 2 coordinates.
1631  * @param       v3              vertex 3 coordinates.
1632  * @param       v4              vertex 4 coordinates.
1633  * @return      number of vertices of this face
1634  */
1635 static int face_get_vertex_coordinates(Mesh* mesh, TFace* face, float v1[3], float v2[3], float v3[3], float v4[3])
1636 {
1637         int num_vertices;
1638         MVert *mv;
1639         MFace *mf = (MFace *) (((MFace *)mesh->mface) + (face - (TFace *) mesh->tface));
1640
1641         num_vertices = mf->v4 == 0 ? 3 : 4;
1642         mv = mesh->mvert + mf->v1;
1643         v1[0] = mv->co[0]; v1[1] = mv->co[1]; v1[2] = mv->co[2];
1644         mv = mesh->mvert + mf->v2;
1645         v2[0] = mv->co[0]; v2[1] = mv->co[1]; v2[2] = mv->co[2];
1646         mv = mesh->mvert + mf->v3;
1647         v3[0] = mv->co[0]; v3[1] = mv->co[1]; v3[2] = mv->co[2];
1648         if (num_vertices == 4) {
1649                 mv = mesh->mvert + mf->v4;
1650                 v4[0] = mv->co[0]; v4[1] = mv->co[1]; v4[2] = mv->co[2];
1651         }
1652
1653         return num_vertices;
1654 }
1655
1656 /**
1657  * Finds texture coordinates from face edge interpolation values.
1658  * @author      Maarten Gribnau
1659  * @param       face    the face.
1660  * @param       v1              vertex 1 index.
1661  * @param       v2              vertex 2 index.
1662  * @param       v3              vertex 3 index.
1663  * @param       a               interpolation value of edge v2-v1.
1664  * @param       b               interpolation value of edge v3-v1.
1665  * @param       u               (u,v) coordinate.
1666  * @param       v               (u,v) coordinate.
1667  */
1668 static void face_get_uv(TFace* face, int v1, int v2, int v3, float a, float b, float* u, float* v)
1669 {
1670         float uv01[2], uv21[2];
1671
1672         /* Pin a,b inside [0,1] range */
1673 #if 0
1674         a = (float)fmod(a, 1.);
1675         b = (float)fmod(b, 1.);
1676 #else
1677         if (a < 0.f) a = 0.f;
1678         else if (a > 1.f) a = 1.f;
1679         if (b < 0.f) b = 0.f;
1680         else if (b > 1.f) b = 1.f;
1681 #endif
1682
1683         /* Convert to texture coordinates */
1684         uv01[0] = face->uv[v2][0] - face->uv[v1][0];
1685         uv01[1] = face->uv[v2][1] - face->uv[v1][1];
1686         uv21[0] = face->uv[v3][0] - face->uv[v1][0];
1687         uv21[1] = face->uv[v3][1] - face->uv[v1][1];
1688         uv01[0] *= a;
1689         uv01[1] *= a;
1690         uv21[0] *= b;
1691         uv21[1] *= b;
1692         *u = face->uv[v1][0] + (uv01[0] + uv21[0]);
1693         *v = face->uv[v1][1] + (uv01[1] + uv21[1]);
1694 }
1695
1696 /**
1697  * Get the (u,v) coordinates on a face from a point in screen coordinates.
1698  * The coordinates should be given in viewport coordinates.
1699  * @author      Maarten Gribnau
1700  * @param       object  the object with the mesh
1701  * @param       mesh    the mesh with the face to be picked.
1702  * @param       face    the face to be picked.
1703  * @param       x               the x-coordinate to pick at.
1704  * @param       y               the y-coordinate to pick at.
1705  * @param       u               the u-coordinate calculated.
1706  * @param       v               the v-coordinate calculated.
1707  * @return      intersection result:
1708  *                      0 == no intersection, (u,v) invalid
1709  *                      1 == intersection, (u,v) valid
1710  */
1711 static int face_pick_uv(Object* object, Mesh* mesh, TFace* face, short x, short y, float* u, float* v)
1712 {
1713         float org[3], dir[3];
1714         float ab[2];
1715         float v1[3], v2[3], v3[3], v4[3];
1716         int result;
1717         int num_verts;
1718
1719         /* Get a view ray to intersect with the face */
1720         get_pick_ray(x, y, org, dir);
1721
1722         /* Convert local vertex coordinates to world */
1723         num_verts = face_get_vertex_coordinates(mesh, face, v1, v2, v3, v4);
1724         /* Convert local vertex coordinates to world */
1725         Mat4MulVecfl(object->obmat, v1);
1726         Mat4MulVecfl(object->obmat, v2);
1727         Mat4MulVecfl(object->obmat, v3);
1728         if (num_verts > 3) {
1729                 Mat4MulVecfl(object->obmat, v4);
1730         }
1731
1732         /* Get (u,v) values (local face coordinates) of intersection point
1733          * If face is a quad, there are two triangles to check.
1734          */
1735         result = triangle_ray_intersect(v2, v1, v3, org, dir, ab);
1736         if ( (num_verts == 3) || ((num_verts == 4) && (result > 1)) ) {
1737                 /* Face is a triangle or a quad with a hit on the first triangle */
1738                 face_get_uv(face, 1, 0, 2, ab[0], ab[1], u, v);
1739                 /* printf("triangle 1, texture (u,v)=(%f, %f)\n", *u, *v); */
1740         }
1741         else {
1742                 /* Face is a quad and no intersection with first triangle */
1743                 result = triangle_ray_intersect(v4, v3, v1, org, dir, ab);
1744                 face_get_uv(face, 3, 2, 0, ab[0], ab[1], u, v);
1745                 /* printf("triangle 2, texture (u,v)=(%f, %f)\n", *u, *v); */
1746         }
1747         return result > 0;
1748 }
1749
1750 /**
1751  * First attempt at drawing in the texture of a face.
1752  * @author      Maarten Gribnau
1753  */
1754 void face_draw()
1755 {
1756         Object *ob;
1757         Mesh *me;
1758         TFace *face, *face_old = 0;
1759         short xy[2], xy_old[2];
1760         //int a, index;
1761         Image *img=NULL, *img_old = NULL;
1762         IMG_BrushPtr brush;
1763         IMG_CanvasPtr canvas = 0;
1764         unsigned int rowBytes, face_index;
1765         char *warn_packed_file = 0;
1766         float uv[2], uv_old[2];
1767         extern VPaint Gvp;
1768         short mousebut;
1769
1770         ob = OBACT;
1771         if (!ob) {
1772                 error("No active object"); return;
1773         }
1774         if (!(ob->lay & G.vd->lay)) {
1775                 error("The active object is not in this layer"); return;
1776         }
1777         me = get_mesh(ob);
1778         if (!me) {
1779                 error("The active object does not have a mesh obData"); return;
1780         }
1781
1782         brush = IMG_BrushCreate(Gvp.size, Gvp.size, &Gvp.r);
1783         if (!brush) {
1784                 error("Can't create brush"); return;
1785         }
1786
1787         if (U.flag & USER_LMOUSESELECT) mousebut = R_MOUSE;
1788         else mousebut = L_MOUSE;
1789
1790         persp(PERSP_VIEW);
1791
1792         getmouseco_areawin(xy_old);
1793         while (get_mbut() & mousebut) {
1794                 getmouseco_areawin(xy);
1795                 /* Check if cursor has moved */
1796                 if ((xy[0] != xy_old[0]) || (xy[1] != xy_old[1])) {
1797
1798                         /* Get face to draw on */
1799                         if (!facesel_face_pick(me, xy, &face_index, 0)) face = NULL;
1800                         else face = (((TFace*)me->tface)+face_index);
1801
1802                         /* Check if this is another face. */
1803                         if (face != face_old) {
1804                                 /* The active face changed, check the texture */
1805                                 if (face) {
1806                                         img = face->tpage;
1807                                 }
1808                                 else {
1809                                         img = 0;
1810                                 }
1811
1812                                 if (img != img_old) {
1813                                         /* Faces have different textures. Finish drawing in the old face. */
1814                                         if (face_old && canvas) {
1815                                                 face_pick_uv(ob, me, face_old, xy[0], xy[1], &uv[0], &uv[1]);
1816                                                 IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
1817                                                 img_old->ibuf->userflags |= IB_BITMAPDIRTY;
1818                                                 /* Delete old canvas */
1819                                                 IMG_CanvasDispose(canvas);
1820                                                 canvas = 0;
1821                                         }
1822
1823                                         /* Create new canvas and start drawing in the new face. */
1824                                         if (img) {
1825                                                 if (img->ibuf && img->packedfile == 0) {
1826                                                         /* MAART: skipx is not set most of the times. Make a guess. */
1827                                                         rowBytes = img->ibuf->skipx ? img->ibuf->skipx : img->ibuf->x * 4;
1828                                                         canvas = IMG_CanvasCreateFromPtr(img->ibuf->rect, img->ibuf->x, img->ibuf->y, rowBytes);
1829                                                         if (canvas) {
1830                                                                 face_pick_uv(ob, me, face, xy_old[0], xy_old[1], &uv_old[0], &uv_old[1]);
1831                                                                 face_pick_uv(ob, me, face, xy[0], xy[1], &uv[0], &uv[1]);
1832                                                                 IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
1833                                                                 img->ibuf->userflags |= IB_BITMAPDIRTY;
1834                                                         }
1835                                                 }
1836                                                 else {
1837                                                         /* TODO: should issue warning that no texture is assigned */
1838                                                         if (img->packedfile) {
1839                                                                 warn_packed_file = img->id.name + 2;
1840                                                                 img = 0;
1841                                                         }
1842                                                 }
1843                                         }
1844                                 }
1845                                 else {
1846                                         /* Face changed and faces have the same texture. */
1847                                         if (canvas) {
1848                                                 /* Finish drawing in the old face. */
1849                                                 if (face_old) {
1850                                                         face_pick_uv(ob, me, face_old, xy[0], xy[1], &uv[0], &uv[1]);
1851                                                         IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
1852                                                         img_old->ibuf->userflags |= IB_BITMAPDIRTY;
1853                                                 }
1854
1855                                                 /* Start drawing in the new face. */
1856                                                 if (face) {
1857                                                         face_pick_uv(ob, me, face, xy_old[0], xy_old[1], &uv_old[0], &uv_old[1]);
1858                                                         face_pick_uv(ob, me, face, xy[0], xy[1], &uv[0], &uv[1]);
1859                                                         IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
1860                                                         img->ibuf->userflags |= IB_BITMAPDIRTY;
1861                                                 }
1862                                         }
1863                                 }
1864                         }
1865                         else {
1866                                 /* Same face, continue drawing */
1867                                 if (face && canvas) {
1868                                         /* Get the new (u,v) coordinates */
1869                                         face_pick_uv(ob, me, face, xy[0], xy[1], &uv[0], &uv[1]);
1870                                         IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
1871                                         img->ibuf->userflags |= IB_BITMAPDIRTY;
1872                                 }
1873                         }
1874
1875                         if (face && img) {
1876                                 /* Make OpenGL aware of a change in the texture */
1877                                 free_realtime_image(img);
1878                                 /* Redraw the view */
1879                                 scrarea_do_windraw(curarea);
1880                                 screen_swapbuffers();
1881                         }
1882
1883                         xy_old[0] = xy[0];
1884                         xy_old[1] = xy[1];
1885                         uv_old[0] = uv[0];
1886                         uv_old[1] = uv[1];
1887                         face_old = face;
1888                         img_old = img;
1889                 }
1890         }
1891
1892         IMG_BrushDispose(brush);
1893         if (canvas) {
1894                 IMG_CanvasDispose(canvas);
1895                 canvas = 0;
1896         }
1897
1898         if (warn_packed_file) {
1899                 error("Painting in packed images is not supported: %s", warn_packed_file);
1900         }
1901
1902         persp(PERSP_WIN);
1903
1904         BIF_undo_push("UV face draw");
1905         allqueue(REDRAWVIEW3D, 0);
1906         allqueue(REDRAWIMAGE, 0);
1907         allqueue(REDRAWHEADERS, 0);
1908 }
1909
1910  /* Selects all faces which have the same uv-texture as the active face 
1911  * @author      Roel Spruit
1912  * @return      Void
1913  * Errors:      - Active object not in this layer
1914  *              - No active face or active face has no UV-texture                       
1915  */
1916 void get_same_uv(void)
1917 {
1918         Object *ob;
1919         Mesh *me;
1920         TFace *tface;   
1921         short a, foundtex=0;
1922         Image *ima;
1923         char uvname[160];
1924         
1925         ob = OBACT;
1926         if (!(ob->lay & G.vd->lay)) {
1927                 error("The active object is not in this layer");
1928                 return;
1929         }
1930         me = get_mesh(ob);
1931         
1932                 
1933         /* Search for the active face with a UV-Texture */
1934         tface = me->tface;
1935         a = me->totface;
1936         while (a--) {           
1937                 if(tface->flag & TF_ACTIVE){                    
1938                         ima=tface->tpage;
1939                         if(ima && ima->name){
1940                                 strcpy(uvname,ima->name);                       
1941                                 a=0;
1942                                 foundtex=1;
1943                         }
1944                 }
1945                 tface++;
1946         }               
1947         
1948         if(!foundtex) {
1949                 error("No active face, or active face has no UV texture");
1950                 return;
1951         }
1952
1953         /* select everything with the same texture */
1954         tface = me->tface;
1955         a = me->totface;
1956         while (a--) {           
1957                 ima=tface->tpage;
1958                 if(ima && ima->name){
1959                         if(!strcmp(ima->name, uvname)){
1960                                 tface->flag |= TF_SELECT;
1961                         }
1962                         else tface->flag &= ~TF_SELECT;
1963                 }
1964                 else tface->flag &= ~TF_SELECT;
1965                 tface++;
1966         }
1967         
1968         /* image window redraw */
1969         BIF_undo_push("Get same UV");
1970
1971         object_tface_flags_changed(OBACT, 0);
1972 }
1973