Seam Cutting in Faceselect Mode:
[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         BIF_undo_push("Mark Seam");
1217
1218         object_tface_flags_changed(OBACT, 1);
1219 }
1220
1221 void face_select()
1222 {
1223         Object *ob;
1224         Mesh *me;
1225         TFace *tface, *tsel;
1226         MFace *msel;
1227         short mval[2];
1228         unsigned int a, index;
1229
1230         /* Get the face under the cursor */
1231         ob = OBACT;
1232         if (!(ob->lay & G.vd->lay)) {
1233                 error("The active object is not in this layer");
1234         }
1235         me = get_mesh(ob);
1236         getmouseco_areawin(mval);
1237
1238         if (G.qual & LR_ALTKEY) {
1239                 seam_select(me, mval, (G.qual & LR_SHIFTKEY) != 0);
1240                 return;
1241         }
1242
1243         if (!facesel_face_pick(me, mval, &index, 1)) return;
1244         
1245         tsel= (((TFace*)me->tface)+index);
1246         msel= (((MFace*)me->mface)+index);
1247
1248         if (tsel->flag & TF_HIDE) return;
1249         
1250         /* clear flags */
1251         tface = me->tface;
1252         a = me->totface;
1253         while (a--) {
1254                 if (G.qual & LR_SHIFTKEY)
1255                         tface->flag &= ~TF_ACTIVE;
1256                 else
1257                         tface->flag &= ~(TF_ACTIVE+TF_SELECT);
1258                 tface++;
1259         }
1260         
1261         tsel->flag |= TF_ACTIVE;
1262
1263         if (G.qual & LR_SHIFTKEY) {
1264                 if (tsel->flag & TF_SELECT)
1265                         tsel->flag &= ~TF_SELECT;
1266                 else
1267                         tsel->flag |= TF_SELECT;
1268         }
1269         else tsel->flag |= TF_SELECT;
1270         
1271         /* image window redraw */
1272         
1273         BIF_undo_push("Select UV face");
1274
1275         object_tface_flags_changed(OBACT, 1);
1276 }
1277
1278 void face_borderselect()
1279 {
1280         Mesh *me;
1281         TFace *tface;
1282         rcti rect;
1283         struct ImBuf *ibuf;
1284         unsigned int *rt;
1285         int a, sx, sy, index, val;
1286         char *selar;
1287         
1288         me= get_mesh(OBACT);
1289         if(me==0 || me->tface==0) return;
1290         if(me->totface==0) return;
1291         
1292         val= get_border(&rect, 3);
1293         
1294         /* why readbuffer here? shouldn't be necessary (maybe a flush or so) */
1295         glReadBuffer(GL_BACK);
1296 #ifdef __APPLE__
1297         glReadBuffer(GL_AUX0); /* apple only */
1298 #endif
1299         
1300         if(val) {
1301                 selar= MEM_callocN(me->totface+1, "selar");
1302                 
1303                 sx= (rect.xmax-rect.xmin+1);
1304                 sy= (rect.ymax-rect.ymin+1);
1305                 if(sx*sy<=0) return;
1306
1307                 ibuf = IMB_allocImBuf(sx,sy,32,0,0);
1308                 rt = ibuf->rect;
1309                 glReadPixels(rect.xmin+curarea->winrct.xmin,  rect.ymin+curarea->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE,  ibuf->rect);
1310                 if(G.order==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
1311
1312                 a= sx*sy;
1313                 while(a--) {
1314                         if(*rt) {
1315                                 index= framebuffer_to_index(*rt);
1316                                 if(index<=me->totface) selar[index]= 1;
1317                         }
1318                         rt++;
1319                 }
1320                 
1321                 tface= me->tface;
1322                 for(a=1; a<=me->totface; a++, tface++) {
1323                         if(selar[a]) {
1324                                 if(tface->flag & TF_HIDE);
1325                                 else {
1326                                         if(val==LEFTMOUSE) tface->flag |= TF_SELECT;
1327                                         else tface->flag &= ~TF_SELECT;
1328                                 }
1329                         }
1330                 }
1331                 
1332                 IMB_freeImBuf(ibuf);
1333                 MEM_freeN(selar);
1334
1335                 BIF_undo_push("Border Select UV face");
1336
1337                 object_tface_flags_changed(OBACT, 0);
1338         }
1339 #ifdef __APPLE__        
1340         glReadBuffer(GL_BACK);
1341 #endif
1342 }
1343
1344 /* Pupmenu codes: */
1345 #define UV_CUBE_MAPPING 2
1346 #define UV_CYL_MAPPING 3
1347 #define UV_SPHERE_MAPPING 4
1348 #define UV_BOUNDS8_MAPPING 68
1349 #define UV_BOUNDS4_MAPPING 65
1350 #define UV_BOUNDS2_MAPPING 66
1351 #define UV_BOUNDS1_MAPPING 67
1352 #define UV_STD8_MAPPING 131
1353 #define UV_STD4_MAPPING 130
1354 #define UV_STD2_MAPPING 129
1355 #define UV_STD1_MAPPING 128
1356 #define UV_WINDOW_MAPPING 5
1357 #define UV_UNWRAP_MAPPING 6
1358 #define UV_CYL_EX 32
1359 #define UV_SPHERE_EX 34
1360
1361 /* Some macro tricks to make pupmenu construction look nicer :-)
1362    Sorry, just did it for fun. */
1363
1364 #define _STR(x) " " #x
1365 #define STRING(x) _STR(x)
1366
1367 #define MENUSTRING(string, code) string " %x" STRING(code)
1368 #define MENUTITLE(string) string " %t|" 
1369
1370 void uv_autocalc_tface()
1371 {
1372         short mode;
1373         mode= pupmenu(MENUTITLE("UV Calculation")
1374                       MENUSTRING("Cube",          UV_CUBE_MAPPING) "|"
1375                       MENUSTRING("Cylinder",      UV_CYL_MAPPING) "|"
1376                       MENUSTRING("Sphere",        UV_SPHERE_MAPPING) "|"
1377                       MENUSTRING("Unwrap",          UV_UNWRAP_MAPPING) "|"
1378                       MENUSTRING("Bounds to 1/8", UV_BOUNDS8_MAPPING) "|"
1379                       MENUSTRING("Bounds to 1/4", UV_BOUNDS4_MAPPING) "|"
1380                       MENUSTRING("Bounds to 1/2", UV_BOUNDS2_MAPPING) "|"
1381                       MENUSTRING("Bounds to 1/1", UV_BOUNDS1_MAPPING) "|"
1382                       MENUSTRING("Standard 1/8",  UV_STD8_MAPPING) "|"
1383                       MENUSTRING("Standard 1/4",  UV_STD4_MAPPING) "|"
1384                       MENUSTRING("Standard 1/2",  UV_STD2_MAPPING) "|"
1385                       MENUSTRING("Standard 1/1",  UV_STD1_MAPPING) "|"
1386                       MENUSTRING("From Window",   UV_WINDOW_MAPPING) );
1387         
1388         
1389         switch(mode) {
1390         case UV_CUBE_MAPPING:
1391                 calculate_uv_map(B_UVAUTO_CUBE); break;
1392         case UV_CYL_MAPPING:
1393                 calculate_uv_map(B_UVAUTO_CYLINDER); break;
1394         case UV_SPHERE_MAPPING:
1395                 calculate_uv_map(B_UVAUTO_SPHERE); break;
1396         case UV_BOUNDS8_MAPPING:
1397                 calculate_uv_map(B_UVAUTO_BOUNDS8); break;
1398         case UV_BOUNDS4_MAPPING:
1399                 calculate_uv_map(B_UVAUTO_BOUNDS4); break;
1400         case UV_BOUNDS2_MAPPING:
1401                 calculate_uv_map(B_UVAUTO_BOUNDS2); break;
1402         case UV_BOUNDS1_MAPPING:
1403                 calculate_uv_map(B_UVAUTO_BOUNDS1); break;
1404         case UV_STD8_MAPPING:
1405                 calculate_uv_map(B_UVAUTO_STD8); break;
1406         case UV_STD4_MAPPING:
1407                 calculate_uv_map(B_UVAUTO_STD4); break;
1408         case UV_STD2_MAPPING:
1409                 calculate_uv_map(B_UVAUTO_STD2); break;
1410         case UV_STD1_MAPPING:
1411                 calculate_uv_map(B_UVAUTO_STD1); break;
1412         case UV_WINDOW_MAPPING:
1413                 calculate_uv_map(B_UVAUTO_WINDOW); break;
1414         case UV_UNWRAP_MAPPING:
1415                 unwrap_lscm(0); break;
1416         }
1417 }
1418
1419 void set_faceselect()   /* toggle */
1420 {
1421         Object *ob = OBACT;
1422         Mesh *me = 0;
1423         
1424         scrarea_queue_headredraw(curarea);
1425         if(ob==NULL || ob->id.lib) return;
1426         
1427         if(G.f & G_FACESELECT) G.f &= ~G_FACESELECT;
1428         else {
1429                 if (ob && ob->type == OB_MESH) G.f |= G_FACESELECT;
1430         }
1431
1432         allqueue(REDRAWVIEW3D, 0);
1433         allqueue(REDRAWBUTSEDIT, 0);
1434         allqueue(REDRAWIMAGE, 0);
1435         
1436         ob= OBACT;
1437         me= get_mesh(ob);
1438         if(me && me->tface==NULL) make_tfaces(me);
1439
1440         if(G.f & G_FACESELECT) {
1441                 setcursor_space(SPACE_VIEW3D, CURSOR_FACESEL);
1442                 BIF_undo_push("Set UV Faceselect");
1443         }
1444         else if((G.f & (G_WEIGHTPAINT|G_VERTEXPAINT|G_TEXTUREPAINT))==0) {
1445                 if(me) {
1446                         reveal_tface();
1447                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1448                 }
1449                 setcursor_space(SPACE_VIEW3D, CURSOR_STD);
1450                 BIF_undo_push("End UV Faceselect");
1451         }
1452         countall();
1453 }
1454
1455
1456 /**
1457  * Get the view ray through the screen point.
1458  * Uses the OpenGL settings of the active view port.
1459  * The coordinates should be given in viewport coordinates.
1460  * @author      Maarten Gribnau
1461  * @param       x               the x-coordinate of the screen point.
1462  * @param       y               the y-coordinate of the screen point.
1463  * @param       org             origin of the view ray.
1464  * @param       dir             direction of the view ray.
1465  */
1466 static void get_pick_ray(short x, short y, float org[3], float dir[3])
1467 {
1468         double mvmatrix[16];
1469         double projmatrix[16];
1470         GLint viewport[4];
1471         double px, py, pz;
1472         float l;
1473
1474         /* Get the matrices needed for gluUnProject */
1475         glGetIntegerv(GL_VIEWPORT, viewport);
1476         glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
1477         glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
1478
1479         /* Set up viewport so that gluUnProject will give correct values */
1480         viewport[0] = 0;
1481         viewport[1] = 0;
1482         /* printf("viewport = (%4d, %4d, %4d, %4d)\n", viewport[0], viewport[1], viewport[2], viewport[3]); */
1483         /* printf("cursor = (%4d, %4d)\n", x, y); */
1484
1485         gluUnProject((GLdouble) x, (GLdouble) y, 0.0, mvmatrix, projmatrix, viewport, &px, &py, &pz);
1486         org[0] = (float)px; org[1] = (float)py; org[2] = (float)pz;
1487         /* printf("world point at z=0.0 is (%f, %f, %f)\n", org[0], org[1], org[2]); */
1488         gluUnProject((GLdouble) x, (GLdouble) y, 1.0, mvmatrix, projmatrix, viewport, &px, &py, &pz); 
1489         /* printf("world point at z=1.0 is (%f, %f, %f)\n", px, py, pz); */
1490         dir[0] = ((float)px) - org[0];
1491         dir[1] = ((float)py) - org[1];
1492         dir[2] = ((float)pz) - org[2];
1493         l = (float)sqrt(dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]);
1494         if (!l) return;
1495         l = 1. / l;
1496         dir[0] *= l; dir[1] *= l; dir[2] *= l;
1497         /* printf("ray org. is (%f, %f, %f)\n", org[0], org[1], org[2]); */
1498         /* printf("ray dir. is (%f, %f, %f)\n", dir[0], dir[1], dir[2]); */
1499 }
1500
1501
1502 static int triangle_ray_intersect(float tv0[3], float tv1[3], float tv2[3], float org[3], float dir[3], float uv[2])
1503 {
1504         float v1v0[3];
1505         float v2v0[3];
1506         float n[3], an[3];
1507         float t, d, l;
1508         float p[3];
1509         double u0, v0, u1, v1, u2, v2, uvtemp;
1510         unsigned int iu, iv;
1511
1512         /* Calculate normal of the plane (cross, normalize)
1513          * Could really use moto here...
1514          */
1515         v1v0[0] = tv1[0] - tv0[0];
1516         v1v0[1] = tv1[1] - tv0[1];
1517         v1v0[2] = tv1[2] - tv0[2];
1518         v2v0[0] = tv2[0] - tv0[0];
1519         v2v0[1] = tv2[1] - tv0[1];
1520         v2v0[2] = tv2[2] - tv0[2];
1521         n[0] = (v1v0[1] * v2v0[2]) - (v1v0[2] * v2v0[1]);
1522         n[1] = (v1v0[2] * v2v0[0]) - (v1v0[0] * v2v0[2]);
1523         n[2] = (v1v0[0] * v2v0[1]) - (v1v0[1] * v2v0[0]);
1524         l = sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
1525         if (!l) return 0;
1526         l = 1. / l;
1527         n[0] *= l; n[1] *= l; n[2] *= l;
1528
1529         /* Calculate intersection point */
1530         t = n[0]*dir[0] + n[1]*dir[1] + n[2]*dir[2];
1531         if (fabs(t) < 1.0e-6) return 0;
1532         d = -(n[0]*tv0[0] + n[1]*tv0[1] + n[2]*tv0[2]);
1533         t = -(((n[0]*org[0] + n[1]*org[1] + n[2]*org[2]) + d) / t);
1534         if (t < 0) return 0;
1535         p[0] = org[0] + dir[0]*t;
1536         p[1] = org[1] + dir[1]*t;
1537         p[2] = org[2] + dir[2]*t;
1538         /*printf("intersection at (%f, %f, %f)\n", p[0], p[1], p[2]);*/
1539
1540         /* Calculate the largest component of the normal */
1541         an[0] = fabs(n[0]); an[1] = fabs(n[1]); an[2] = fabs(n[2]);
1542         if ((an[0] > an[1]) && (an[0] > an[2])) {
1543                 iu = 1; iv = 2;
1544         }
1545         else if ((an[1] > an[0]) && (an[1] > an[2])) {
1546                 iu = 2; iv = 0;
1547         }
1548         else {
1549                 iu = 0; iv = 1;
1550         }
1551         /* printf("iu, iv = (%d, %d)\n", iu, iv); */
1552
1553         /* Calculate (u,v) */
1554         u0 = p[iu] - tv0[iu];
1555         v0 = p[iv] - tv0[iv];
1556         u1 = tv1[iu] - tv0[iu];
1557         v1 = tv1[iv] - tv0[iv];
1558         u2 = tv2[iu] - tv0[iu];
1559         v2 = tv2[iv] - tv0[iv];
1560         /* printf("u0, v0, u1, v1, u2, v2 = (%f, %f, %f, %f, %f, %f)\n", u0, v0, u1, v1, u2, v2); */
1561
1562         /* These calculations should be in double precision.
1563          * On windows we get inpredictable results in single precision
1564          */
1565         if (u1 == 0) {
1566                 uvtemp = u0/u2;
1567                 uv[1] = (float)uvtemp;
1568                 /* if ((uv[1] >= 0.) && (uv[1] <= 1.)) { */
1569                         uv[0] = (float)((v0 - uvtemp*v2) / v1);
1570                 /* } */
1571         }
1572         else {
1573                 uvtemp = (v0*u1 - u0*v1)/(v2*u1-u2*v1);
1574                 uv[1] = (float)uvtemp;
1575                 /* if ((uv[1] >= 0) && (uv[1] <= 1)) { */
1576                         uv[0] = (float)((u0 - uvtemp*u2) / u1);
1577                 /* } */
1578         }
1579         /* printf("uv[0], uv[1] = (%f, %f)\n", uv[0], uv[1]); */
1580         return ((uv[0] >= 0) && (uv[1] >= 0) && ((uv[0]+uv[1]) <= 1)) ? 2 : 1;
1581 }
1582
1583 /**
1584  * Returns the vertex (local) coordinates of a face.
1585  * No bounds checking!
1586  * @author      Maarten Gribnau
1587  * @param       mesh    the mesh with the face.
1588  * @param       face    the face.
1589  * @param       v1              vertex 1 coordinates.
1590  * @param       v2              vertex 2 coordinates.
1591  * @param       v3              vertex 3 coordinates.
1592  * @param       v4              vertex 4 coordinates.
1593  * @return      number of vertices of this face
1594  */
1595 static int face_get_vertex_coordinates(Mesh* mesh, TFace* face, float v1[3], float v2[3], float v3[3], float v4[3])
1596 {
1597         int num_vertices;
1598         MVert *mv;
1599         MFace *mf = (MFace *) (((MFace *)mesh->mface) + (face - (TFace *) mesh->tface));
1600
1601         num_vertices = mf->v4 == 0 ? 3 : 4;
1602         mv = mesh->mvert + mf->v1;
1603         v1[0] = mv->co[0]; v1[1] = mv->co[1]; v1[2] = mv->co[2];
1604         mv = mesh->mvert + mf->v2;
1605         v2[0] = mv->co[0]; v2[1] = mv->co[1]; v2[2] = mv->co[2];
1606         mv = mesh->mvert + mf->v3;
1607         v3[0] = mv->co[0]; v3[1] = mv->co[1]; v3[2] = mv->co[2];
1608         if (num_vertices == 4) {
1609                 mv = mesh->mvert + mf->v4;
1610                 v4[0] = mv->co[0]; v4[1] = mv->co[1]; v4[2] = mv->co[2];
1611         }
1612
1613         return num_vertices;
1614 }
1615
1616 /**
1617  * Finds texture coordinates from face edge interpolation values.
1618  * @author      Maarten Gribnau
1619  * @param       face    the face.
1620  * @param       v1              vertex 1 index.
1621  * @param       v2              vertex 2 index.
1622  * @param       v3              vertex 3 index.
1623  * @param       a               interpolation value of edge v2-v1.
1624  * @param       b               interpolation value of edge v3-v1.
1625  * @param       u               (u,v) coordinate.
1626  * @param       v               (u,v) coordinate.
1627  */
1628 static void face_get_uv(TFace* face, int v1, int v2, int v3, float a, float b, float* u, float* v)
1629 {
1630         float uv01[2], uv21[2];
1631
1632         /* Pin a,b inside [0,1] range */
1633 #if 0
1634         a = (float)fmod(a, 1.);
1635         b = (float)fmod(b, 1.);
1636 #else
1637         if (a < 0.f) a = 0.f;
1638         else if (a > 1.f) a = 1.f;
1639         if (b < 0.f) b = 0.f;
1640         else if (b > 1.f) b = 1.f;
1641 #endif
1642
1643         /* Convert to texture coordinates */
1644         uv01[0] = face->uv[v2][0] - face->uv[v1][0];
1645         uv01[1] = face->uv[v2][1] - face->uv[v1][1];
1646         uv21[0] = face->uv[v3][0] - face->uv[v1][0];
1647         uv21[1] = face->uv[v3][1] - face->uv[v1][1];
1648         uv01[0] *= a;
1649         uv01[1] *= a;
1650         uv21[0] *= b;
1651         uv21[1] *= b;
1652         *u = face->uv[v1][0] + (uv01[0] + uv21[0]);
1653         *v = face->uv[v1][1] + (uv01[1] + uv21[1]);
1654 }
1655
1656 /**
1657  * Get the (u,v) coordinates on a face from a point in screen coordinates.
1658  * The coordinates should be given in viewport coordinates.
1659  * @author      Maarten Gribnau
1660  * @param       object  the object with the mesh
1661  * @param       mesh    the mesh with the face to be picked.
1662  * @param       face    the face to be picked.
1663  * @param       x               the x-coordinate to pick at.
1664  * @param       y               the y-coordinate to pick at.
1665  * @param       u               the u-coordinate calculated.
1666  * @param       v               the v-coordinate calculated.
1667  * @return      intersection result:
1668  *                      0 == no intersection, (u,v) invalid
1669  *                      1 == intersection, (u,v) valid
1670  */
1671 static int face_pick_uv(Object* object, Mesh* mesh, TFace* face, short x, short y, float* u, float* v)
1672 {
1673         float org[3], dir[3];
1674         float ab[2];
1675         float v1[3], v2[3], v3[3], v4[3];
1676         int result;
1677         int num_verts;
1678
1679         /* Get a view ray to intersect with the face */
1680         get_pick_ray(x, y, org, dir);
1681
1682         /* Convert local vertex coordinates to world */
1683         num_verts = face_get_vertex_coordinates(mesh, face, v1, v2, v3, v4);
1684         /* Convert local vertex coordinates to world */
1685         Mat4MulVecfl(object->obmat, v1);
1686         Mat4MulVecfl(object->obmat, v2);
1687         Mat4MulVecfl(object->obmat, v3);
1688         if (num_verts > 3) {
1689                 Mat4MulVecfl(object->obmat, v4);
1690         }
1691
1692         /* Get (u,v) values (local face coordinates) of intersection point
1693          * If face is a quad, there are two triangles to check.
1694          */
1695         result = triangle_ray_intersect(v2, v1, v3, org, dir, ab);
1696         if ( (num_verts == 3) || ((num_verts == 4) && (result > 1)) ) {
1697                 /* Face is a triangle or a quad with a hit on the first triangle */
1698                 face_get_uv(face, 1, 0, 2, ab[0], ab[1], u, v);
1699                 /* printf("triangle 1, texture (u,v)=(%f, %f)\n", *u, *v); */
1700         }
1701         else {
1702                 /* Face is a quad and no intersection with first triangle */
1703                 result = triangle_ray_intersect(v4, v3, v1, org, dir, ab);
1704                 face_get_uv(face, 3, 2, 0, ab[0], ab[1], u, v);
1705                 /* printf("triangle 2, texture (u,v)=(%f, %f)\n", *u, *v); */
1706         }
1707         return result > 0;
1708 }
1709
1710 /**
1711  * First attempt at drawing in the texture of a face.
1712  * @author      Maarten Gribnau
1713  */
1714 void face_draw()
1715 {
1716         Object *ob;
1717         Mesh *me;
1718         TFace *face, *face_old = 0;
1719         short xy[2], xy_old[2];
1720         //int a, index;
1721         Image *img=NULL, *img_old = NULL;
1722         IMG_BrushPtr brush;
1723         IMG_CanvasPtr canvas = 0;
1724         unsigned int rowBytes, face_index;
1725         char *warn_packed_file = 0;
1726         float uv[2], uv_old[2];
1727         extern VPaint Gvp;
1728         short mousebut;
1729
1730         ob = OBACT;
1731         if (!ob) {
1732                 error("No active object"); return;
1733         }
1734         if (!(ob->lay & G.vd->lay)) {
1735                 error("The active object is not in this layer"); return;
1736         }
1737         me = get_mesh(ob);
1738         if (!me) {
1739                 error("The active object does not have a mesh obData"); return;
1740         }
1741
1742         brush = IMG_BrushCreate(Gvp.size, Gvp.size, &Gvp.r);
1743         if (!brush) {
1744                 error("Can't create brush"); return;
1745         }
1746
1747         if (U.flag & USER_LMOUSESELECT) mousebut = R_MOUSE;
1748         else mousebut = L_MOUSE;
1749
1750         persp(PERSP_VIEW);
1751
1752         getmouseco_areawin(xy_old);
1753         while (get_mbut() & mousebut) {
1754                 getmouseco_areawin(xy);
1755                 /* Check if cursor has moved */
1756                 if ((xy[0] != xy_old[0]) || (xy[1] != xy_old[1])) {
1757
1758                         /* Get face to draw on */
1759                         if (!facesel_face_pick(me, xy, &face_index, 0)) face = NULL;
1760                         else face = (((TFace*)me->tface)+face_index);
1761
1762                         /* Check if this is another face. */
1763                         if (face != face_old) {
1764                                 /* The active face changed, check the texture */
1765                                 if (face) {
1766                                         img = face->tpage;
1767                                 }
1768                                 else {
1769                                         img = 0;
1770                                 }
1771
1772                                 if (img != img_old) {
1773                                         /* Faces have different textures. Finish drawing in the old face. */
1774                                         if (face_old && canvas) {
1775                                                 face_pick_uv(ob, me, face_old, xy[0], xy[1], &uv[0], &uv[1]);
1776                                                 IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
1777                                                 img_old->ibuf->userflags |= IB_BITMAPDIRTY;
1778                                                 /* Delete old canvas */
1779                                                 IMG_CanvasDispose(canvas);
1780                                                 canvas = 0;
1781                                         }
1782
1783                                         /* Create new canvas and start drawing in the new face. */
1784                                         if (img) {
1785                                                 if (img->ibuf && img->packedfile == 0) {
1786                                                         /* MAART: skipx is not set most of the times. Make a guess. */
1787                                                         rowBytes = img->ibuf->skipx ? img->ibuf->skipx : img->ibuf->x * 4;
1788                                                         canvas = IMG_CanvasCreateFromPtr(img->ibuf->rect, img->ibuf->x, img->ibuf->y, rowBytes);
1789                                                         if (canvas) {
1790                                                                 face_pick_uv(ob, me, face, xy_old[0], xy_old[1], &uv_old[0], &uv_old[1]);
1791                                                                 face_pick_uv(ob, me, face, xy[0], xy[1], &uv[0], &uv[1]);
1792                                                                 IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
1793                                                                 img->ibuf->userflags |= IB_BITMAPDIRTY;
1794                                                         }
1795                                                 }
1796                                                 else {
1797                                                         /* TODO: should issue warning that no texture is assigned */
1798                                                         if (img->packedfile) {
1799                                                                 warn_packed_file = img->id.name + 2;
1800                                                                 img = 0;
1801                                                         }
1802                                                 }
1803                                         }
1804                                 }
1805                                 else {
1806                                         /* Face changed and faces have the same texture. */
1807                                         if (canvas) {
1808                                                 /* Finish drawing in the old face. */
1809                                                 if (face_old) {
1810                                                         face_pick_uv(ob, me, face_old, xy[0], xy[1], &uv[0], &uv[1]);
1811                                                         IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
1812                                                         img_old->ibuf->userflags |= IB_BITMAPDIRTY;
1813                                                 }
1814
1815                                                 /* Start drawing in the new face. */
1816                                                 if (face) {
1817                                                         face_pick_uv(ob, me, face, xy_old[0], xy_old[1], &uv_old[0], &uv_old[1]);
1818                                                         face_pick_uv(ob, me, face, xy[0], xy[1], &uv[0], &uv[1]);
1819                                                         IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
1820                                                         img->ibuf->userflags |= IB_BITMAPDIRTY;
1821                                                 }
1822                                         }
1823                                 }
1824                         }
1825                         else {
1826                                 /* Same face, continue drawing */
1827                                 if (face && canvas) {
1828                                         /* Get the new (u,v) coordinates */
1829                                         face_pick_uv(ob, me, face, xy[0], xy[1], &uv[0], &uv[1]);
1830                                         IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
1831                                         img->ibuf->userflags |= IB_BITMAPDIRTY;
1832                                 }
1833                         }
1834
1835                         if (face && img) {
1836                                 /* Make OpenGL aware of a change in the texture */
1837                                 free_realtime_image(img);
1838                                 /* Redraw the view */
1839                                 scrarea_do_windraw(curarea);
1840                                 screen_swapbuffers();
1841                         }
1842
1843                         xy_old[0] = xy[0];
1844                         xy_old[1] = xy[1];
1845                         uv_old[0] = uv[0];
1846                         uv_old[1] = uv[1];
1847                         face_old = face;
1848                         img_old = img;
1849                 }
1850         }
1851
1852         IMG_BrushDispose(brush);
1853         if (canvas) {
1854                 IMG_CanvasDispose(canvas);
1855                 canvas = 0;
1856         }
1857
1858         if (warn_packed_file) {
1859                 error("Painting in packed images is not supported: %s", warn_packed_file);
1860         }
1861
1862         persp(PERSP_WIN);
1863
1864         BIF_undo_push("UV face draw");
1865         allqueue(REDRAWVIEW3D, 0);
1866         allqueue(REDRAWIMAGE, 0);
1867         allqueue(REDRAWHEADERS, 0);
1868 }
1869
1870  /* Selects all faces which have the same uv-texture as the active face 
1871  * @author      Roel Spruit
1872  * @return      Void
1873  * Errors:      - Active object not in this layer
1874  *              - No active face or active face has no UV-texture                       
1875  */
1876 void get_same_uv(void)
1877 {
1878         Object *ob;
1879         Mesh *me;
1880         TFace *tface;   
1881         short a, foundtex=0;
1882         Image *ima;
1883         char uvname[160];
1884         
1885         ob = OBACT;
1886         if (!(ob->lay & G.vd->lay)) {
1887                 error("The active object is not in this layer");
1888                 return;
1889         }
1890         me = get_mesh(ob);
1891         
1892                 
1893         /* Search for the active face with a UV-Texture */
1894         tface = me->tface;
1895         a = me->totface;
1896         while (a--) {           
1897                 if(tface->flag & TF_ACTIVE){                    
1898                         ima=tface->tpage;
1899                         if(ima && ima->name){
1900                                 strcpy(uvname,ima->name);                       
1901                                 a=0;
1902                                 foundtex=1;
1903                         }
1904                 }
1905                 tface++;
1906         }               
1907         
1908         if(!foundtex) {
1909                 error("No active face, or active face has no UV texture");
1910                 return;
1911         }
1912
1913         /* select everything with the same texture */
1914         tface = me->tface;
1915         a = me->totface;
1916         while (a--) {           
1917                 ima=tface->tpage;
1918                 if(ima && ima->name){
1919                         if(!strcmp(ima->name, uvname)){
1920                                 tface->flag |= TF_SELECT;
1921                         }
1922                         else tface->flag &= ~TF_SELECT;
1923                 }
1924                 else tface->flag &= ~TF_SELECT;
1925                 tface++;
1926         }
1927         
1928         /* image window redraw */
1929         BIF_undo_push("Get same UV");
1930
1931         object_tface_flags_changed(OBACT, 0);
1932 }
1933