6d87d6e2eac44286867213550c4446ce4a7e7bae
[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(G.f & G_FACESELECT) {
1439                 G.f &= ~G_FACESELECT;
1440
1441                 if((G.f & (G_WEIGHTPAINT|G_VERTEXPAINT|G_TEXTUREPAINT))==0) {
1442                         if(me) {
1443                                 reveal_tface();
1444                                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1445                         }
1446                         setcursor_space(SPACE_VIEW3D, CURSOR_STD);
1447                         BIF_undo_push("End UV Faceselect");
1448                 }
1449         }
1450         else if (me) {
1451                 G.f |= G_FACESELECT;
1452                 if(me->tface==NULL)
1453                         make_tfaces(me);
1454
1455                 setcursor_space(SPACE_VIEW3D, CURSOR_FACESEL);
1456                 BIF_undo_push("Set UV Faceselect");
1457         }
1458
1459         countall();
1460
1461         allqueue(REDRAWVIEW3D, 0);
1462         allqueue(REDRAWBUTSEDIT, 0);
1463         allqueue(REDRAWIMAGE, 0);
1464 }
1465
1466
1467 /**
1468  * Get the view ray through the screen point.
1469  * Uses the OpenGL settings of the active view port.
1470  * The coordinates should be given in viewport coordinates.
1471  * @author      Maarten Gribnau
1472  * @param       x               the x-coordinate of the screen point.
1473  * @param       y               the y-coordinate of the screen point.
1474  * @param       org             origin of the view ray.
1475  * @param       dir             direction of the view ray.
1476  */
1477 static void get_pick_ray(short x, short y, float org[3], float dir[3])
1478 {
1479         double mvmatrix[16];
1480         double projmatrix[16];
1481         GLint viewport[4];
1482         double px, py, pz;
1483         float l;
1484
1485         /* Get the matrices needed for gluUnProject */
1486         glGetIntegerv(GL_VIEWPORT, viewport);
1487         glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
1488         glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
1489
1490         /* Set up viewport so that gluUnProject will give correct values */
1491         viewport[0] = 0;
1492         viewport[1] = 0;
1493         /* printf("viewport = (%4d, %4d, %4d, %4d)\n", viewport[0], viewport[1], viewport[2], viewport[3]); */
1494         /* printf("cursor = (%4d, %4d)\n", x, y); */
1495
1496         gluUnProject((GLdouble) x, (GLdouble) y, 0.0, mvmatrix, projmatrix, viewport, &px, &py, &pz);
1497         org[0] = (float)px; org[1] = (float)py; org[2] = (float)pz;
1498         /* printf("world point at z=0.0 is (%f, %f, %f)\n", org[0], org[1], org[2]); */
1499         gluUnProject((GLdouble) x, (GLdouble) y, 1.0, mvmatrix, projmatrix, viewport, &px, &py, &pz); 
1500         /* printf("world point at z=1.0 is (%f, %f, %f)\n", px, py, pz); */
1501         dir[0] = ((float)px) - org[0];
1502         dir[1] = ((float)py) - org[1];
1503         dir[2] = ((float)pz) - org[2];
1504         l = (float)sqrt(dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]);
1505         if (!l) return;
1506         l = 1. / l;
1507         dir[0] *= l; dir[1] *= l; dir[2] *= l;
1508         /* printf("ray org. is (%f, %f, %f)\n", org[0], org[1], org[2]); */
1509         /* printf("ray dir. is (%f, %f, %f)\n", dir[0], dir[1], dir[2]); */
1510 }
1511
1512
1513 static int triangle_ray_intersect(float tv0[3], float tv1[3], float tv2[3], float org[3], float dir[3], float uv[2])
1514 {
1515         float v1v0[3];
1516         float v2v0[3];
1517         float n[3], an[3];
1518         float t, d, l;
1519         float p[3];
1520         double u0, v0, u1, v1, u2, v2, uvtemp;
1521         unsigned int iu, iv;
1522
1523         /* Calculate normal of the plane (cross, normalize)
1524          * Could really use moto here...
1525          */
1526         v1v0[0] = tv1[0] - tv0[0];
1527         v1v0[1] = tv1[1] - tv0[1];
1528         v1v0[2] = tv1[2] - tv0[2];
1529         v2v0[0] = tv2[0] - tv0[0];
1530         v2v0[1] = tv2[1] - tv0[1];
1531         v2v0[2] = tv2[2] - tv0[2];
1532         n[0] = (v1v0[1] * v2v0[2]) - (v1v0[2] * v2v0[1]);
1533         n[1] = (v1v0[2] * v2v0[0]) - (v1v0[0] * v2v0[2]);
1534         n[2] = (v1v0[0] * v2v0[1]) - (v1v0[1] * v2v0[0]);
1535         l = sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
1536         if (!l) return 0;
1537         l = 1. / l;
1538         n[0] *= l; n[1] *= l; n[2] *= l;
1539
1540         /* Calculate intersection point */
1541         t = n[0]*dir[0] + n[1]*dir[1] + n[2]*dir[2];
1542         if (fabs(t) < 1.0e-6) return 0;
1543         d = -(n[0]*tv0[0] + n[1]*tv0[1] + n[2]*tv0[2]);
1544         t = -(((n[0]*org[0] + n[1]*org[1] + n[2]*org[2]) + d) / t);
1545         if (t < 0) return 0;
1546         p[0] = org[0] + dir[0]*t;
1547         p[1] = org[1] + dir[1]*t;
1548         p[2] = org[2] + dir[2]*t;
1549         /*printf("intersection at (%f, %f, %f)\n", p[0], p[1], p[2]);*/
1550
1551         /* Calculate the largest component of the normal */
1552         an[0] = fabs(n[0]); an[1] = fabs(n[1]); an[2] = fabs(n[2]);
1553         if ((an[0] > an[1]) && (an[0] > an[2])) {
1554                 iu = 1; iv = 2;
1555         }
1556         else if ((an[1] > an[0]) && (an[1] > an[2])) {
1557                 iu = 2; iv = 0;
1558         }
1559         else {
1560                 iu = 0; iv = 1;
1561         }
1562         /* printf("iu, iv = (%d, %d)\n", iu, iv); */
1563
1564         /* Calculate (u,v) */
1565         u0 = p[iu] - tv0[iu];
1566         v0 = p[iv] - tv0[iv];
1567         u1 = tv1[iu] - tv0[iu];
1568         v1 = tv1[iv] - tv0[iv];
1569         u2 = tv2[iu] - tv0[iu];
1570         v2 = tv2[iv] - tv0[iv];
1571         /* printf("u0, v0, u1, v1, u2, v2 = (%f, %f, %f, %f, %f, %f)\n", u0, v0, u1, v1, u2, v2); */
1572
1573         /* These calculations should be in double precision.
1574          * On windows we get inpredictable results in single precision
1575          */
1576         if (u1 == 0) {
1577                 uvtemp = u0/u2;
1578                 uv[1] = (float)uvtemp;
1579                 /* if ((uv[1] >= 0.) && (uv[1] <= 1.)) { */
1580                         uv[0] = (float)((v0 - uvtemp*v2) / v1);
1581                 /* } */
1582         }
1583         else {
1584                 uvtemp = (v0*u1 - u0*v1)/(v2*u1-u2*v1);
1585                 uv[1] = (float)uvtemp;
1586                 /* if ((uv[1] >= 0) && (uv[1] <= 1)) { */
1587                         uv[0] = (float)((u0 - uvtemp*u2) / u1);
1588                 /* } */
1589         }
1590         /* printf("uv[0], uv[1] = (%f, %f)\n", uv[0], uv[1]); */
1591         return ((uv[0] >= 0) && (uv[1] >= 0) && ((uv[0]+uv[1]) <= 1)) ? 2 : 1;
1592 }
1593
1594 /**
1595  * Returns the vertex (local) coordinates of a face.
1596  * No bounds checking!
1597  * @author      Maarten Gribnau
1598  * @param       mesh    the mesh with the face.
1599  * @param       face    the face.
1600  * @param       v1              vertex 1 coordinates.
1601  * @param       v2              vertex 2 coordinates.
1602  * @param       v3              vertex 3 coordinates.
1603  * @param       v4              vertex 4 coordinates.
1604  * @return      number of vertices of this face
1605  */
1606 static int face_get_vertex_coordinates(Mesh* mesh, TFace* face, float v1[3], float v2[3], float v3[3], float v4[3])
1607 {
1608         int num_vertices;
1609         MVert *mv;
1610         MFace *mf = (MFace *) (((MFace *)mesh->mface) + (face - (TFace *) mesh->tface));
1611
1612         num_vertices = mf->v4 == 0 ? 3 : 4;
1613         mv = mesh->mvert + mf->v1;
1614         v1[0] = mv->co[0]; v1[1] = mv->co[1]; v1[2] = mv->co[2];
1615         mv = mesh->mvert + mf->v2;
1616         v2[0] = mv->co[0]; v2[1] = mv->co[1]; v2[2] = mv->co[2];
1617         mv = mesh->mvert + mf->v3;
1618         v3[0] = mv->co[0]; v3[1] = mv->co[1]; v3[2] = mv->co[2];
1619         if (num_vertices == 4) {
1620                 mv = mesh->mvert + mf->v4;
1621                 v4[0] = mv->co[0]; v4[1] = mv->co[1]; v4[2] = mv->co[2];
1622         }
1623
1624         return num_vertices;
1625 }
1626
1627 /**
1628  * Finds texture coordinates from face edge interpolation values.
1629  * @author      Maarten Gribnau
1630  * @param       face    the face.
1631  * @param       v1              vertex 1 index.
1632  * @param       v2              vertex 2 index.
1633  * @param       v3              vertex 3 index.
1634  * @param       a               interpolation value of edge v2-v1.
1635  * @param       b               interpolation value of edge v3-v1.
1636  * @param       u               (u,v) coordinate.
1637  * @param       v               (u,v) coordinate.
1638  */
1639 static void face_get_uv(TFace* face, int v1, int v2, int v3, float a, float b, float* u, float* v)
1640 {
1641         float uv01[2], uv21[2];
1642
1643         /* Pin a,b inside [0,1] range */
1644 #if 0
1645         a = (float)fmod(a, 1.);
1646         b = (float)fmod(b, 1.);
1647 #else
1648         if (a < 0.f) a = 0.f;
1649         else if (a > 1.f) a = 1.f;
1650         if (b < 0.f) b = 0.f;
1651         else if (b > 1.f) b = 1.f;
1652 #endif
1653
1654         /* Convert to texture coordinates */
1655         uv01[0] = face->uv[v2][0] - face->uv[v1][0];
1656         uv01[1] = face->uv[v2][1] - face->uv[v1][1];
1657         uv21[0] = face->uv[v3][0] - face->uv[v1][0];
1658         uv21[1] = face->uv[v3][1] - face->uv[v1][1];
1659         uv01[0] *= a;
1660         uv01[1] *= a;
1661         uv21[0] *= b;
1662         uv21[1] *= b;
1663         *u = face->uv[v1][0] + (uv01[0] + uv21[0]);
1664         *v = face->uv[v1][1] + (uv01[1] + uv21[1]);
1665 }
1666
1667 /**
1668  * Get the (u,v) coordinates on a face from a point in screen coordinates.
1669  * The coordinates should be given in viewport coordinates.
1670  * @author      Maarten Gribnau
1671  * @param       object  the object with the mesh
1672  * @param       mesh    the mesh with the face to be picked.
1673  * @param       face    the face to be picked.
1674  * @param       x               the x-coordinate to pick at.
1675  * @param       y               the y-coordinate to pick at.
1676  * @param       u               the u-coordinate calculated.
1677  * @param       v               the v-coordinate calculated.
1678  * @return      intersection result:
1679  *                      0 == no intersection, (u,v) invalid
1680  *                      1 == intersection, (u,v) valid
1681  */
1682 static int face_pick_uv(Object* object, Mesh* mesh, TFace* face, short x, short y, float* u, float* v)
1683 {
1684         float org[3], dir[3];
1685         float ab[2];
1686         float v1[3], v2[3], v3[3], v4[3];
1687         int result;
1688         int num_verts;
1689
1690         /* Get a view ray to intersect with the face */
1691         get_pick_ray(x, y, org, dir);
1692
1693         /* Convert local vertex coordinates to world */
1694         num_verts = face_get_vertex_coordinates(mesh, face, v1, v2, v3, v4);
1695         /* Convert local vertex coordinates to world */
1696         Mat4MulVecfl(object->obmat, v1);
1697         Mat4MulVecfl(object->obmat, v2);
1698         Mat4MulVecfl(object->obmat, v3);
1699         if (num_verts > 3) {
1700                 Mat4MulVecfl(object->obmat, v4);
1701         }
1702
1703         /* Get (u,v) values (local face coordinates) of intersection point
1704          * If face is a quad, there are two triangles to check.
1705          */
1706         result = triangle_ray_intersect(v2, v1, v3, org, dir, ab);
1707         if ( (num_verts == 3) || ((num_verts == 4) && (result > 1)) ) {
1708                 /* Face is a triangle or a quad with a hit on the first triangle */
1709                 face_get_uv(face, 1, 0, 2, ab[0], ab[1], u, v);
1710                 /* printf("triangle 1, texture (u,v)=(%f, %f)\n", *u, *v); */
1711         }
1712         else {
1713                 /* Face is a quad and no intersection with first triangle */
1714                 result = triangle_ray_intersect(v4, v3, v1, org, dir, ab);
1715                 face_get_uv(face, 3, 2, 0, ab[0], ab[1], u, v);
1716                 /* printf("triangle 2, texture (u,v)=(%f, %f)\n", *u, *v); */
1717         }
1718         return result > 0;
1719 }
1720
1721 /**
1722  * First attempt at drawing in the texture of a face.
1723  * @author      Maarten Gribnau
1724  */
1725 void face_draw()
1726 {
1727         Object *ob;
1728         Mesh *me;
1729         TFace *face, *face_old = 0;
1730         short xy[2], xy_old[2];
1731         //int a, index;
1732         Image *img=NULL, *img_old = NULL;
1733         IMG_BrushPtr brush;
1734         IMG_CanvasPtr canvas = 0;
1735         unsigned int rowBytes, face_index;
1736         char *warn_packed_file = 0;
1737         float uv[2], uv_old[2];
1738         extern VPaint Gvp;
1739         short mousebut;
1740
1741         ob = OBACT;
1742         if (!ob) {
1743                 error("No active object"); return;
1744         }
1745         if (!(ob->lay & G.vd->lay)) {
1746                 error("The active object is not in this layer"); return;
1747         }
1748         me = get_mesh(ob);
1749         if (!me) {
1750                 error("The active object does not have a mesh obData"); return;
1751         }
1752
1753         brush = IMG_BrushCreate(Gvp.size, Gvp.size, &Gvp.r);
1754         if (!brush) {
1755                 error("Can't create brush"); return;
1756         }
1757
1758         if (U.flag & USER_LMOUSESELECT) mousebut = R_MOUSE;
1759         else mousebut = L_MOUSE;
1760
1761         persp(PERSP_VIEW);
1762
1763         getmouseco_areawin(xy_old);
1764         while (get_mbut() & mousebut) {
1765                 getmouseco_areawin(xy);
1766                 /* Check if cursor has moved */
1767                 if ((xy[0] != xy_old[0]) || (xy[1] != xy_old[1])) {
1768
1769                         /* Get face to draw on */
1770                         if (!facesel_face_pick(me, xy, &face_index, 0)) face = NULL;
1771                         else face = (((TFace*)me->tface)+face_index);
1772
1773                         /* Check if this is another face. */
1774                         if (face != face_old) {
1775                                 /* The active face changed, check the texture */
1776                                 if (face) {
1777                                         img = face->tpage;
1778                                 }
1779                                 else {
1780                                         img = 0;
1781                                 }
1782
1783                                 if (img != img_old) {
1784                                         /* Faces have different textures. Finish drawing in the old face. */
1785                                         if (face_old && canvas) {
1786                                                 face_pick_uv(ob, me, face_old, xy[0], xy[1], &uv[0], &uv[1]);
1787                                                 IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
1788                                                 img_old->ibuf->userflags |= IB_BITMAPDIRTY;
1789                                                 /* Delete old canvas */
1790                                                 IMG_CanvasDispose(canvas);
1791                                                 canvas = 0;
1792                                         }
1793
1794                                         /* Create new canvas and start drawing in the new face. */
1795                                         if (img) {
1796                                                 if (img->ibuf && img->packedfile == 0) {
1797                                                         /* MAART: skipx is not set most of the times. Make a guess. */
1798                                                         rowBytes = img->ibuf->skipx ? img->ibuf->skipx : img->ibuf->x * 4;
1799                                                         canvas = IMG_CanvasCreateFromPtr(img->ibuf->rect, img->ibuf->x, img->ibuf->y, rowBytes);
1800                                                         if (canvas) {
1801                                                                 face_pick_uv(ob, me, face, xy_old[0], xy_old[1], &uv_old[0], &uv_old[1]);
1802                                                                 face_pick_uv(ob, me, face, xy[0], xy[1], &uv[0], &uv[1]);
1803                                                                 IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
1804                                                                 img->ibuf->userflags |= IB_BITMAPDIRTY;
1805                                                         }
1806                                                 }
1807                                                 else {
1808                                                         /* TODO: should issue warning that no texture is assigned */
1809                                                         if (img->packedfile) {
1810                                                                 warn_packed_file = img->id.name + 2;
1811                                                                 img = 0;
1812                                                         }
1813                                                 }
1814                                         }
1815                                 }
1816                                 else {
1817                                         /* Face changed and faces have the same texture. */
1818                                         if (canvas) {
1819                                                 /* Finish drawing in the old face. */
1820                                                 if (face_old) {
1821                                                         face_pick_uv(ob, me, face_old, xy[0], xy[1], &uv[0], &uv[1]);
1822                                                         IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
1823                                                         img_old->ibuf->userflags |= IB_BITMAPDIRTY;
1824                                                 }
1825
1826                                                 /* Start drawing in the new face. */
1827                                                 if (face) {
1828                                                         face_pick_uv(ob, me, face, xy_old[0], xy_old[1], &uv_old[0], &uv_old[1]);
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                         }
1836                         else {
1837                                 /* Same face, continue drawing */
1838                                 if (face && canvas) {
1839                                         /* Get the new (u,v) coordinates */
1840                                         face_pick_uv(ob, me, face, xy[0], xy[1], &uv[0], &uv[1]);
1841                                         IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
1842                                         img->ibuf->userflags |= IB_BITMAPDIRTY;
1843                                 }
1844                         }
1845
1846                         if (face && img) {
1847                                 /* Make OpenGL aware of a change in the texture */
1848                                 free_realtime_image(img);
1849                                 /* Redraw the view */
1850                                 scrarea_do_windraw(curarea);
1851                                 screen_swapbuffers();
1852                         }
1853
1854                         xy_old[0] = xy[0];
1855                         xy_old[1] = xy[1];
1856                         uv_old[0] = uv[0];
1857                         uv_old[1] = uv[1];
1858                         face_old = face;
1859                         img_old = img;
1860                 }
1861         }
1862
1863         IMG_BrushDispose(brush);
1864         if (canvas) {
1865                 IMG_CanvasDispose(canvas);
1866                 canvas = 0;
1867         }
1868
1869         if (warn_packed_file) {
1870                 error("Painting in packed images is not supported: %s", warn_packed_file);
1871         }
1872
1873         persp(PERSP_WIN);
1874
1875         BIF_undo_push("UV face draw");
1876         allqueue(REDRAWVIEW3D, 0);
1877         allqueue(REDRAWIMAGE, 0);
1878         allqueue(REDRAWHEADERS, 0);
1879 }
1880
1881  /* Selects all faces which have the same uv-texture as the active face 
1882  * @author      Roel Spruit
1883  * @return      Void
1884  * Errors:      - Active object not in this layer
1885  *              - No active face or active face has no UV-texture                       
1886  */
1887 void get_same_uv(void)
1888 {
1889         Object *ob;
1890         Mesh *me;
1891         TFace *tface;   
1892         short a, foundtex=0;
1893         Image *ima;
1894         char uvname[160];
1895         
1896         ob = OBACT;
1897         if (!(ob->lay & G.vd->lay)) {
1898                 error("The active object is not in this layer");
1899                 return;
1900         }
1901         me = get_mesh(ob);
1902         
1903                 
1904         /* Search for the active face with a UV-Texture */
1905         tface = me->tface;
1906         a = me->totface;
1907         while (a--) {           
1908                 if(tface->flag & TF_ACTIVE){                    
1909                         ima=tface->tpage;
1910                         if(ima && ima->name){
1911                                 strcpy(uvname,ima->name);                       
1912                                 a=0;
1913                                 foundtex=1;
1914                         }
1915                 }
1916                 tface++;
1917         }               
1918         
1919         if(!foundtex) {
1920                 error("No active face, or active face has no UV texture");
1921                 return;
1922         }
1923
1924         /* select everything with the same texture */
1925         tface = me->tface;
1926         a = me->totface;
1927         while (a--) {           
1928                 ima=tface->tpage;
1929                 if(ima && ima->name){
1930                         if(!strcmp(ima->name, uvname)){
1931                                 tface->flag |= TF_SELECT;
1932                         }
1933                         else tface->flag &= ~TF_SELECT;
1934                 }
1935                 else tface->flag &= ~TF_SELECT;
1936                 tface++;
1937         }
1938         
1939         /* image window redraw */
1940         BIF_undo_push("Get same UV");
1941
1942         object_tface_flags_changed(OBACT, 0);
1943 }
1944