6f79f1daae9ad6bc51691c3ff443a8cad0030454
[blender.git] / source / blender / src / editsima.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 #include <stdlib.h>
34 #include <string.h>
35 #include <math.h>
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #ifndef WIN32
42 #include <unistd.h>
43 #else
44 #include <io.h>
45 #endif   
46 #include "MEM_guardedalloc.h"
47
48 #include "BLI_blenlib.h"
49 #include "BLI_arithb.h"
50
51 #include "IMB_imbuf_types.h"
52
53 #include "DNA_mesh_types.h"
54 #include "DNA_meshdata_types.h"
55 #include "DNA_scene_types.h"
56 #include "DNA_screen_types.h"
57 #include "DNA_userdef_types.h"
58 #include "DNA_space_types.h"
59 #include "DNA_image_types.h"
60 #include "DNA_object_types.h" // only for uvedit_selectionCB() (struct Object)
61
62 #include "BKE_depsgraph.h"
63 #include "BKE_global.h"
64 #include "BKE_mesh.h"
65 #include "BKE_displist.h"
66 #include "BKE_object.h"
67 #include "BKE_utildefines.h"
68
69 #include "BIF_gl.h"
70 #include "BIF_interface.h"
71 #include "BIF_screen.h"
72 #include "BIF_drawimage.h"
73 #include "BIF_editview.h"
74 #include "BIF_space.h"
75 #include "BIF_editsima.h"
76 #include "BIF_toolbox.h"
77 #include "BIF_mywindow.h"
78
79 #include "BSE_drawipo.h"
80 #include "BSE_edit.h"
81 #include "BSE_trans_types.h"
82
83 #include "BDR_editobject.h"
84 #include "BDR_unwrapper.h"
85
86 #include "blendef.h"
87 #include "mydevice.h"
88
89 struct uvvertsort {
90         unsigned int v, f;
91         unsigned char tf_sel;
92         char flag;
93 };
94
95 /* local prototypes */
96 void clever_numbuts_sima(void);
97 void sel_uvco_inside_radius(short , TFace *, int , float *, float *, short);
98 void uvedit_selectionCB(short , Object *, short *, float ); /* used in edit.c*/ 
99
100 static int compuvvert(const void *u1, const void *u2)
101 {
102         const struct uvvertsort *v1=u1, *v2=u2;
103         if (v1->v > v2->v) return 1;
104         else if (v1->v < v2->v) return -1;
105         return 0;
106 }
107
108 void object_uvs_changed(Object *ob)
109 {
110         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
111
112         allqueue(REDRAWVIEW3D, 0);
113         allqueue(REDRAWIMAGE, 0);
114 }
115
116 void object_tface_flags_changed(Object *ob, int updateButtons)
117 {
118         if (updateButtons) allqueue(REDRAWBUTSEDIT, 0);
119         allqueue(REDRAWVIEW3D, 0);
120         allqueue(REDRAWIMAGE, 0);
121 }
122
123 int is_uv_tface_editing_allowed_silent(void)
124 {
125         Mesh *me;
126
127         if(G.obedit) return 0;
128         if(G.sima->mode!=SI_TEXTURE) return 0;
129         if(!(G.f & G_FACESELECT)) return 0;  
130         me= get_mesh(OBACT);
131         if(me==0 || me->tface==0) return 0;
132         
133         return 1;
134 }
135
136 int is_uv_tface_editing_allowed(void)
137 {
138         if(G.obedit) error("Unable to perform action in Edit Mode");
139
140         return is_uv_tface_editing_allowed_silent();
141 }
142
143 void get_connected_limit_tface_uv(float *limit)
144 {
145         if(G.sima->image && G.sima->image->ibuf && G.sima->image->ibuf->x > 0 &&
146            G.sima->image->ibuf->y > 0) {
147                 limit[0]= 0.05/(float)G.sima->image->ibuf->x;
148                 limit[1]= 0.05/(float)G.sima->image->ibuf->y;
149         }
150         else
151                 limit[0]= limit[1]= 0.05/256.0;
152 }
153
154 void clever_numbuts_sima(void)
155 {
156         float ocent[2], cent[2]= {0.0, 0.0};
157         int imx, imy;
158         int i, nactive= 0;
159         Mesh *me;
160         
161         if( is_uv_tface_editing_allowed()==0 ) return;
162         me= get_mesh(OBACT);
163         
164         if (G.sima->image && G.sima->image->ibuf) {
165                 imx= G.sima->image->ibuf->x;
166                 imy= G.sima->image->ibuf->y;
167         } else
168                 imx= imy= 256;
169         
170         for (i=0; i<me->totface; i++) {
171                 MFace *mf= &((MFace*) me->mface)[i];
172                 TFace *tf= &((TFace*) me->tface)[i];
173                 
174                 if (!(tf->flag & TF_SELECT))
175                         continue;
176                 
177                 if (tf->flag & TF_SEL1) {
178                         cent[0]+= tf->uv[0][0];
179                         cent[1]+= tf->uv[0][1];
180                         nactive++;
181                 }
182                 if (tf->flag & TF_SEL2) {
183                         cent[0]+= tf->uv[1][0];
184                         cent[1]+= tf->uv[1][1];
185                         nactive++;
186                 }
187                 if (tf->flag & TF_SEL3) {
188                         cent[0]+= tf->uv[2][0];
189                         cent[1]+= tf->uv[2][1];
190                         nactive++;
191                 }
192                 if (mf->v4 && (tf->flag & TF_SEL4)) {
193                         cent[0]+= tf->uv[3][0];
194                         cent[1]+= tf->uv[3][1];
195                         nactive++;
196                 }
197         }
198         
199         if (nactive) {
200                 cent[0]= (cent[0]*imx)/nactive;
201                 cent[1]= (cent[1]*imy)/nactive;
202
203                 add_numbut(0, NUM|FLO, "LocX:", -imx*20, imx*20, &cent[0], NULL);
204                 add_numbut(1, NUM|FLO, "LocY:", -imy*20, imy*20, &cent[1], NULL);
205                 
206                 ocent[0]= cent[0];
207                 ocent[1]= cent[1];
208                 if (do_clever_numbuts((nactive==1)?"Active Vertex":"Selected Center", 2, REDRAW)) {
209                         float delta[2];
210                         
211                         delta[0]= (cent[0]-ocent[0])/imx;
212                         delta[1]= (cent[1]-ocent[1])/imy;
213
214                         for (i=0; i<me->totface; i++) {
215                                 MFace *mf= &((MFace*) me->mface)[i];
216                                 TFace *tf= &((TFace*) me->tface)[i];
217                         
218                                 if (!(tf->flag & TF_SELECT))
219                                         continue;
220                         
221                                 if (tf->flag & TF_SEL1) {
222                                         tf->uv[0][0]+= delta[0];
223                                         tf->uv[0][1]+= delta[1];
224                                 }
225                                 if (tf->flag & TF_SEL2) {
226                                         tf->uv[1][0]+= delta[0];
227                                         tf->uv[1][1]+= delta[1];
228                                 }
229                                 if (tf->flag & TF_SEL3) {
230                                         tf->uv[2][0]+= delta[0];
231                                         tf->uv[2][1]+= delta[1];
232                                 }
233                                 if (mf->v4 && (tf->flag & TF_SEL4)) {
234                                         tf->uv[3][0]+= delta[0];
235                                         tf->uv[3][1]+= delta[1];
236                                 }
237                         }
238                         
239                         object_uvs_changed(OBACT);
240                 }
241         }
242 }
243
244 static void sima_pixelgrid(float *loc, float sx, float sy)
245 {
246         float y;
247         float x;
248
249         if(G.sima->flag & SI_PIXELSNAP) {
250                 if(G.sima->image && G.sima->image->ibuf) {
251                         x= G.sima->image->ibuf->x;
252                         y= G.sima->image->ibuf->y;
253                 
254                         sx= floor(x*sx)/x;
255                         if(G.sima->flag & SI_CLIP_UV) {
256                                 CLAMP(sx, 0, 1.0);
257                         }
258                         loc[0]= sx;
259                         
260                         sy= floor(y*sy)/y;
261                         if(G.sima->flag & SI_CLIP_UV) {
262                                 CLAMP(sy, 0, 1.0);
263                         }
264                         loc[1]= sy;
265                 }
266                 else {
267                         loc[0]= sx;
268                         loc[1]= sy;
269                 }
270         }
271         else {
272                 loc[0]= sx;
273                 loc[1]= sy;
274         }
275 }
276
277
278 static void be_square_tface_uv(Mesh *me)
279 {
280         TFace *tface;
281         MFace *mface;
282         int a;
283         
284         /* if 1 vertex selected: doit (with the selected vertex) */
285         mface= (MFace*)me->mface;
286         tface= (TFace*)me->tface;
287         for(a=me->totface; a>0; a--, tface++, mface++) {
288                 if(mface->v4) {
289                         if(tface->flag & TF_SELECT) {
290                                 if(tface->flag & TF_SEL1) {
291                                         if( tface->uv[1][0] == tface->uv[2][0] ) {
292                                                 tface->uv[1][1]= tface->uv[0][1];
293                                                 tface->uv[3][0]= tface->uv[0][0];
294                                         }
295                                         else {  
296                                                 tface->uv[1][0]= tface->uv[0][0];
297                                                 tface->uv[3][1]= tface->uv[0][1];
298                                         }
299                                         
300                                 }
301                                 if(tface->flag & TF_SEL2) {
302                                         if( tface->uv[2][1] == tface->uv[3][1] ) {
303                                                 tface->uv[2][0]= tface->uv[1][0];
304                                                 tface->uv[0][1]= tface->uv[1][1];
305                                         }
306                                         else {
307                                                 tface->uv[2][1]= tface->uv[1][1];
308                                                 tface->uv[0][0]= tface->uv[1][0];
309                                         }
310
311                                 }
312                                 if(tface->flag & TF_SEL3) {
313                                         if( tface->uv[3][0] == tface->uv[0][0] ) {
314                                                 tface->uv[3][1]= tface->uv[2][1];
315                                                 tface->uv[1][0]= tface->uv[2][0];
316                                         }
317                                         else {
318                                                 tface->uv[3][0]= tface->uv[2][0];
319                                                 tface->uv[1][1]= tface->uv[2][1];
320                                         }
321                                 }
322                                 if(tface->flag & TF_SEL4) {
323                                         if( tface->uv[0][1] == tface->uv[1][1] ) {
324                                                 tface->uv[0][0]= tface->uv[3][0];
325                                                 tface->uv[2][1]= tface->uv[3][1];
326                                         }
327                                         else  {
328                                                 tface->uv[0][1]= tface->uv[3][1];
329                                                 tface->uv[2][0]= tface->uv[3][0];
330                                         }
331
332                                 }
333                         }
334                 }
335         }
336
337 }
338
339 void tface_do_clip(void)
340 {
341         Mesh *me;
342         TFace *tface;
343         int a, b;
344         
345         if( is_uv_tface_editing_allowed()==0 ) return;
346         me= get_mesh(OBACT);
347         tface= me->tface;
348         
349         for(a=0; a<me->totface; a++, tface++) {
350                 if(tface->flag & TF_SELECT) {
351                         for(b=0; b<4; b++) {
352                                 CLAMP(tface->uv[b][0], 0.0, 1.0);
353                                 CLAMP(tface->uv[b][1], 0.0, 1.0);
354                         }
355                 }
356         }
357         
358 }
359
360 void transform_tface_uv(int mode, int context)  // 2 args, for callback
361 {
362         MFace *mface;
363         TFace *tface;
364         Mesh *me;
365         TransVert *transmain, *tv;
366
367         float dist, xdist, ydist, aspx, aspy;
368         float asp, dx1, dx2, dy1, dy2, phi, dphi, co, si;
369         float size[2], sizefac;
370         float dx, dy, dvec2[2], dvec[2], div, cent[2];
371         float x, y, min[2], max[2], vec[2], xtra[2], ivec[2];
372         int xim, yim, tot=0, a, b, firsttime=1, afbreek=0;
373         int propmode= 0, proptot= 0, midtog= 0, proj= 0, prop_recalc= 1;
374         unsigned short event = 0;
375         short mval[2], val, xo, yo, xn, yn, xc, yc;
376         char str[80];
377         extern float prop_size, prop_cent[3]; 
378         
379         if( is_uv_tface_editing_allowed()==0 ) return;
380         me= get_mesh(OBACT);
381         
382         if(G.scene->proportional) propmode= 1;
383         
384         min[0]= min[1]= 10000.0;
385         max[0]= max[1]= -10000.0;
386         
387         calc_image_view(G.sima, 'f');
388         
389         if(G.sima->image && G.sima->image->ibuf) {
390                 xim= G.sima->image->ibuf->x;
391                 yim= G.sima->image->ibuf->y;
392         }
393         else {
394                 xim= yim= 256;
395         }
396         aspx = (float)xim/256.0;
397         aspy = (float)yim/256.0;
398
399         /* which vertices are involved? */
400         tface= me->tface;
401         mface= me->mface;
402         for(a=me->totface; a>0; a--, tface++, mface++) {
403                 if(tface->flag & TF_SELECT) {
404                         if(tface->flag & TF_SEL1) tot++;
405                         if(tface->flag & TF_SEL2) tot++;
406                         if(tface->flag & TF_SEL3) tot++;
407                         if(mface->v4 && (tface->flag & TF_SEL4)) tot++;
408                         if(propmode) {
409                                 if(mface->v4) proptot+=4;
410                                 else proptot+=3;
411                         }
412                 }
413         }
414         if(tot==0) return;
415         if(propmode) tot= proptot;
416
417         G.moving= 1;
418         prop_size/= 3;
419         
420         tv=transmain= MEM_callocN(tot*sizeof(TransVert), "transmain");
421
422         tface= me->tface;
423         mface= me->mface;
424         for(a=me->totface; a>0; a--, tface++, mface++) {
425                 if(tface->flag & TF_SELECT) {
426                         if (tface->flag & TF_SEL1 || propmode) {
427                                 tv->loc= tface->uv[0];
428                                 if(tface->flag & TF_SEL1) tv->flag= 1;
429                                 tv++;
430                         }
431                         if (tface->flag & TF_SEL2 || propmode) {
432                                 tv->loc= tface->uv[1];
433                                 if(tface->flag & TF_SEL2) tv->flag= 1;
434                                 tv++;
435                         }
436                         if (tface->flag & TF_SEL3 || propmode) {
437                                 tv->loc= tface->uv[2];
438                                 if(tface->flag & TF_SEL3) tv->flag= 1;
439                                 tv++;
440                         }
441                         if(mface->v4) {
442                                 if (tface->flag & TF_SEL4 || propmode) {
443                                         tv->loc= tface->uv[3];
444                                         if(tface->flag & TF_SEL4) tv->flag= 1;
445                                         tv++;
446                                 }
447                         }
448                 }
449         }
450         
451         a= tot;
452         tv= transmain;
453         while(a--) {
454                 tv->oldloc[0]= tv->loc[0];
455                 tv->oldloc[1]= tv->loc[1];
456                 if(tv->flag) {
457                         DO_MINMAX2(tv->loc, min, max);
458                 }
459                 tv++;
460         }
461
462         cent[0]= (min[0]+max[0])/2.0;
463         cent[1]= (min[1]+max[1])/2.0;
464         prop_cent[0]= cent[0];
465         prop_cent[1]= cent[1];
466
467         ipoco_to_areaco_noclip(G.v2d, cent, mval);
468         xc= mval[0];
469         yc= mval[1];
470         
471         getmouseco_areawin(mval);
472         xo= xn= mval[0];
473         yo= yn= mval[1];
474         dvec[0]= dvec[1]= 0.0;
475         dx1= xc-xn; 
476         dy1= yc-yn;
477         phi= 0.0;
478         
479         
480         sizefac= sqrt( (float)((yc-yn)*(yc-yn)+(xn-xc)*(xn-xc)) );
481         if(sizefac<2.0) sizefac= 2.0;
482
483         while(afbreek==0) {
484                 getmouseco_areawin(mval);
485                 if((mval[0]!=xo || mval[1]!=yo) || firsttime) {
486                         if(propmode && prop_recalc && transmain) {
487                                 a= tot;
488                                 tv= transmain;
489
490                                 while(a--) {
491                                         if(tv->oldloc[0]<min[0]) xdist= tv->oldloc[0]-min[0];
492                                         else if(tv->oldloc[0]>max[0]) xdist= tv->oldloc[0]-max[0];
493                                         else xdist= 0.0;
494                                         xdist*= aspx;
495
496                                         if(tv->oldloc[1]<min[1]) ydist= tv->oldloc[1]-min[1];
497                                         else if(tv->oldloc[1]>max[1]) ydist= tv->oldloc[1]-max[1];
498                                         else ydist= 0.0;
499                                         ydist*= aspy;
500
501                                         dist= sqrt(xdist*xdist + ydist*ydist);
502                                         if(dist==0.0) tv->fac= 1.0;
503                                         else if(dist > prop_size) tv->fac= 0.0;
504                                         else {
505                                                 dist= (prop_size-dist)/prop_size;
506
507                                                 switch(G.scene->prop_mode) {
508                                                 case PROP_SHARP:
509                                                         tv->fac= dist*dist;
510                                                         break;
511                                                 case PROP_SMOOTH:
512                                                         tv->fac= 3.0f*dist*dist - 2.0f*dist*dist*dist;
513                                                         break;
514                                                 case PROP_ROOT:
515                                                         tv->fac= (float)sqrt(dist);
516                                                         break;
517                                                 case PROP_LIN:
518                                                         tv->fac= dist;
519                                                         break;
520                                                 case PROP_CONST:
521                                                         tv->fac= 1.0f;
522                                                         break;
523                                                 case PROP_SPHERE:
524                                                         tv->fac= (float)sqrt(2*dist - dist * dist);
525                                                         break;
526                                                 default:
527                                                         tv->fac= 1;
528                                                 }
529                                         }
530                                         tv++;
531                                 }
532                                 prop_recalc= 0;
533                         }
534                         if(mode=='g') {
535                         
536                                 dx= mval[0]- xo;
537                                 dy= mval[1]- yo;
538         
539                                 div= G.v2d->mask.xmax-G.v2d->mask.xmin;
540                                 dvec[0]+= (G.v2d->cur.xmax-G.v2d->cur.xmin)*(dx)/div;
541         
542                                 div= G.v2d->mask.ymax-G.v2d->mask.ymin;
543                                 dvec[1]+= (G.v2d->cur.ymax-G.v2d->cur.ymin)*(dy)/div;
544                                 
545                                 if(midtog) dvec[proj]= 0.0;
546                                 
547                                 dvec2[0]= dvec[0];
548                                 dvec2[1]= dvec[1];
549                                 apply_keyb_grid(dvec2, 0.0, 1.0/8.0, 1.0/16.0, U.flag & USER_AUTOGRABGRID);
550                                 apply_keyb_grid(dvec2+1, 0.0, 1.0/8.0, 1.0/16.0, U.flag & USER_AUTOGRABGRID);
551
552                                 vec[0]= dvec2[0];
553                                 vec[1]= dvec2[1];
554                                 
555                                 if(G.sima->flag & SI_CLIP_UV) {
556                                         if(vec[0]< -min[0]) vec[0]= -min[0];
557                                         if(vec[1]< -min[1]) vec[1]= -min[1];
558                                         if(vec[0]> 1.0-max[0]) vec[0]= 1.0-max[0];
559                                         if(vec[1]> 1.0-max[1]) vec[1]= 1.0-max[1];
560                                 }
561                                 tv= transmain;
562                                 if (propmode) {
563                                         for(a=0; a<tot; a++, tv++) {
564                                                 x= tv->oldloc[0]+tv->fac*vec[0];
565                                                 y= tv->oldloc[1]+tv->fac*vec[1];
566                                                 
567                                                 sima_pixelgrid(tv->loc, x, y);
568                                         }
569                                 } else {
570                                         for(a=0; a<tot; a++, tv++) {
571                                                 x= tv->oldloc[0]+vec[0];
572                                                 y= tv->oldloc[1]+vec[1];
573                                                 
574                                                 sima_pixelgrid(tv->loc, x, y);
575                                         }
576                                 }
577                                         
578                                 if(G.sima->flag & SI_BE_SQUARE) be_square_tface_uv(me);
579         
580                                 if (G.sima->flag & SI_COORDFLOATS) {
581                                         ivec[0]= vec[0];
582                                         ivec[1]= vec[1];
583                                 }
584                                 else {
585                                         ivec[0]= (vec[0]*xim);
586                                         ivec[1]= (vec[1]*yim);
587                                 }
588                 
589                                 sprintf(str, "X: %.4f   Y: %.4f  ", ivec[0], ivec[1]);
590                                 headerprint(str);
591                         }
592                         else if(mode=='r') {
593
594                                 dx2= xc-mval[0];
595                                 dy2= yc-mval[1];
596                                 
597                                 div= sqrt( (dx1*dx1+dy1*dy1)*(dx2*dx2+dy2*dy2));
598                                 if(div>1.0) {
599                                 
600                                         dphi= (dx1*dx2+dy1*dy2)/div;
601                                         dphi= saacos(dphi);
602                                         if( (dx1*dy2-dx2*dy1)<0.0 ) dphi= -dphi;
603                                         
604                                         if(G.qual & LR_SHIFTKEY) phi+= dphi/30.0;
605                                         else phi+= dphi;
606
607                                         apply_keyb_grid(&phi, 0.0, (5.0/180)*M_PI, (1.0/180)*M_PI, U.flag & USER_AUTOROTGRID);
608                                         
609                                         dx1= dx2; 
610                                         dy1= dy2;
611                                         
612                                         co= cos(phi);
613                                         si= sin(phi);
614                                         asp= (float)yim/(float)xim;
615
616                                         tv= transmain;
617                                         for(a=0; a<tot; a++, tv++) {
618                                                 if(propmode) {
619                                                         co= cos(phi*tv->fac);
620                                                         si= sin(phi*tv->fac);
621                                                 }
622                                                 x= ( co*( tv->oldloc[0]-cent[0]) - si*asp*(tv->oldloc[1]-cent[1]) ) +cent[0];
623                                                 y= ( si*( tv->oldloc[0]-cent[0])/asp + co*(tv->oldloc[1]-cent[1]) ) +cent[1];
624                                                 sima_pixelgrid(tv->loc, x, y);
625                                                 
626                                                 if(G.sima->flag & SI_CLIP_UV) {
627                                                         if(tv->loc[0]<0.0) tv->loc[0]= 0.0;
628                                                         else if(tv->loc[0]>1.0) tv->loc[0]= 1.0;
629                                                         if(tv->loc[1]<0.0) tv->loc[1]= 0.0;
630                                                         else if(tv->loc[1]>1.0) tv->loc[1]= 1.0;
631                                                 }
632                                         }                                       
633                                         
634                                         sprintf(str, "Rot: %.3f  ", phi*180.0/M_PI);
635                                         headerprint(str);
636                                 }
637                         }
638                         else if(mode=='s') {
639                                 size[0]= size[1]= (sqrt((float)((yc-mval[1])*(yc-mval[1])+(mval[0]-xc)*(mval[0]-xc))))/sizefac;
640                                 if(midtog) size[proj]= 1.0;
641                                 
642                                 apply_keyb_grid(size, 0.0, 0.1, 0.01, U.flag & USER_AUTOSIZEGRID);
643                                 apply_keyb_grid(size+1, 0.0, 0.1, 0.01, U.flag & USER_AUTOSIZEGRID);
644
645                                 xtra[0]= xtra[1]= 0;
646
647                                 if(G.sima->flag & SI_CLIP_UV) {
648                                         /* boundbox limit: four step plan: XTRA X */
649         
650                                         a=b= 0;
651                                         if(size[0]*(min[0]-cent[0]) + cent[0] + xtra[0] < 0) 
652                                                 a= -size[0]*(min[0]-cent[0]) - cent[0];
653                                         if(size[0]*(max[0]-cent[0]) + cent[0] + xtra[0] > 1.0) 
654                                                 b= 1.0 - size[0]*(max[0]-cent[0]) - cent[0];
655                                         xtra[0]= (a+b)/2;
656                                         
657                                         /* SIZE X */
658                                         if(size[0]*(min[0]-cent[0]) + cent[0] + xtra[0] < 0) 
659                                                 size[0]= (-cent[0]-xtra[0])/(min[0]-cent[0]);
660                                         if(size[0]*(max[0]-cent[0]) + cent[0] +xtra[0] > 1.0) 
661                                                 size[0]= (1.0-cent[0]-xtra[0])/(max[0]-cent[0]);
662                                                 
663                                         /* XTRA Y */
664                                         a=b= 0;
665                                         if(size[1]*(min[1]-cent[1]) + cent[1] + xtra[1] < 0) 
666                                                 a= -size[1]*(min[1]-cent[1]) - cent[1];
667                                         if(size[1]*(max[1]-cent[1]) + cent[1] + xtra[1] > 1.0) 
668                                                 b= 1.0 - size[1]*(max[1]-cent[1]) - cent[1];
669                                         xtra[1]= (a+b)/2;
670                                         
671                                         /* SIZE Y */
672                                         if(size[1]*(min[1]-cent[1]) + cent[1] +xtra[1] < 0) 
673                                                 size[1]= (-cent[1]-xtra[1])/(min[1]-cent[1]);
674                                         if(size[1]*(max[1]-cent[1]) + cent[1] + xtra[1]> 1.0) 
675                                                 size[1]= (1.0-cent[1]-xtra[1])/(max[1]-cent[1]);
676                                 }
677
678                                 /* if(midtog==0) { */
679                                 /*      if(size[1]>size[0]) size[1]= size[0]; */
680                                 /*      else if(size[0]>size[1]) size[0]= size[1]; */
681                                 /* } */
682
683                                 tv= transmain;
684                                 if (propmode) {
685                                         for(a=0; a<tot; a++, tv++) {
686                                         
687                                                 x= (tv->fac*size[0] + 1.00-tv->fac)*(tv->oldloc[0]-cent[0])+ cent[0] + xtra[0];
688                                                 y= (tv->fac*size[1] + 1.00-tv->fac)*(tv->oldloc[1]-cent[1])+ cent[1] + xtra[1];
689                                                 sima_pixelgrid(tv->loc, x, y);
690                                         }
691
692                                 } else {
693                                         for(a=0; a<tot; a++, tv++) {
694                                         
695                                                 x= size[0]*(tv->oldloc[0]-cent[0])+ cent[0] + xtra[0];
696                                                 y= size[1]*(tv->oldloc[1]-cent[1])+ cent[1] + xtra[1];
697                                                 sima_pixelgrid(tv->loc, x, y);
698                                         }
699                                 }
700                                 
701                                 sprintf(str, "sizeX: %.3f   sizeY: %.3f", size[0], size[1]);
702                                 headerprint(str);
703                         }
704
705                         xo= mval[0];
706                         yo= mval[1];
707                         
708                                 /* Need to force a recalculate since we may be 
709                                  * drawing modified UVs.
710                                  */
711                         if(G.sima->flag & SI_DRAWSHADOW){
712                                 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);        
713                                 object_handle_update(OBACT);
714                         }
715
716                         if(G.sima->lock) {
717                                 force_draw_plus(SPACE_VIEW3D, 0);
718                         }
719                         else force_draw(0);
720                         
721                         firsttime= 0;
722                         
723                 }
724                 else BIF_wait_for_statechange();
725                 
726                 while(qtest()) {
727                         event= extern_qread(&val);
728                         if(val) {
729                                 switch(event) {
730                                 case ESCKEY:
731                                 case RIGHTMOUSE:
732                                 case LEFTMOUSE:
733                                 case SPACEKEY:
734                                 case RETKEY:
735                                         afbreek= 1;
736                                         break;
737                                 case MIDDLEMOUSE:
738                                         midtog= ~midtog;
739                                         if(midtog) {
740                                                 if( abs(mval[0]-xn) > abs(mval[1]-yn)) proj= 1;
741                                                 else proj= 0;
742                                                 firsttime= 1;
743                                         }
744                                         break;
745                                 case WHEELDOWNMOUSE:
746                                 case PADPLUSKEY:
747                                         if(propmode) {
748                                                 prop_size*= 1.1;
749                                                 prop_recalc= 1;
750                                                 firsttime= 1;
751                                         }
752                                         break;
753                                 case WHEELUPMOUSE:
754                                 case PADMINUS:
755                                         if(propmode) {
756                                                 prop_size*= 0.90909090;
757                                                 prop_recalc= 1;
758                                                 firsttime= 1;
759                                         }
760                                         break;
761                                 case WKEY:
762                                 case XKEY:
763                                 case YKEY:
764                                         if(midtog) {
765                                                 if(event==XKEY) {
766                                                         if(proj==1) midtog= ~midtog;
767                                                         else if(proj==0) proj= 1;
768                                                 }
769                                                 else if(event==YKEY) {
770                                                         if(proj==0) midtog= ~midtog;
771                                                         else if(proj==1) proj= 0;
772                                                 }
773                                         }
774                                         else {
775                                                 if(event==XKEY) {
776                                                         midtog= ~midtog;
777                                                         proj= 1;
778                                                 }
779                                                 else if(event==YKEY) {
780                                                         midtog= ~midtog;
781                                                         proj= 0;
782                                                 }
783                                         }
784                                         firsttime= 1;
785                                         break;
786                                 default:
787                                         arrows_move_cursor(event);
788                                 }
789                         }
790
791                         if(afbreek) break;
792                 }
793         }
794         
795         if(event==ESCKEY || event == RIGHTMOUSE) {
796                 tv= transmain;
797                 for(a=0; a<tot; a++, tv++) {
798                         tv->loc[0]= tv->oldloc[0];
799                         tv->loc[1]= tv->oldloc[1];
800                 }
801         }
802
803         MEM_freeN(transmain);
804         
805         if(mode=='g') if(G.sima->flag & SI_BE_SQUARE) be_square_tface_uv(me);
806
807         G.moving= 0;
808         prop_size*= 3;
809         
810         object_uvs_changed(OBACT);
811
812         if(event!=ESCKEY && event!=RIGHTMOUSE)
813                 BIF_undo_push("Transform UV");
814 }
815
816 void mirror_tface_uv(char mirroraxis)
817 {
818         MFace *mface;
819         TFace *tface;
820         Mesh *me;
821         float min[2], max[2], cent[2];
822         int a, axis;
823         
824         if( is_uv_tface_editing_allowed()==0 ) return;
825         me= get_mesh(OBACT);
826         
827         if (!minmax_tface_uv(min, max))
828                 return;
829
830         cent[0]= min[0]+max[0];
831         cent[1]= min[1]+max[1];
832
833         if(mirroraxis=='x') axis= 0;
834         else axis= 1;
835
836         tface= me->tface;
837         mface= me->mface;
838         for(a=me->totface; a>0; a--, tface++, mface++) {
839                 if(tface->flag & TF_SELECT) {
840                         if(tface->flag & TF_SEL1)
841                                 tface->uv[0][axis]= cent[axis] - tface->uv[0][axis];
842                         if(tface->flag & TF_SEL2)
843                                 tface->uv[1][axis]= cent[axis] - tface->uv[1][axis];
844                         if(tface->flag & TF_SEL3)
845                                 tface->uv[2][axis]= cent[axis] - tface->uv[2][axis];
846                         if(mface->v4 && (tface->flag & TF_SEL4))
847                                 tface->uv[3][axis]= cent[axis] - tface->uv[3][axis];
848                 }
849         }
850
851         object_uvs_changed(OBACT);
852 }
853
854 void mirrormenu_tface_uv(void)
855 {
856         short mode= 0;
857
858         if( is_uv_tface_editing_allowed()==0 ) return;
859
860         mode= pupmenu("Mirror%t|X Axis%x1|Y Axis%x2|");
861
862         if(mode==-1) return;
863
864         if(mode==1) mirror_tface_uv('x');
865         else if(mode==2) mirror_tface_uv('y');
866
867         BIF_undo_push("Mirror UV");
868 }
869
870 void weld_align_tface_uv(char tool)
871 {
872         MFace *mface;
873         TFace *tface;
874         Mesh *me;
875         float min[2], max[2], cent[2];
876         int a;
877         
878         if( is_uv_tface_editing_allowed()==0 ) return;
879         me= get_mesh(OBACT);
880
881         if (!minmax_tface_uv(min, max))
882                 return;
883
884         cent[0]= (min[0]+max[0])/2.0;
885         cent[1]= (min[1]+max[1])/2.0;
886
887         if(tool == 'x' || tool == 'w') {
888                 tface= me->tface;
889                 mface= me->mface;
890                 for(a=me->totface; a>0; a--, tface++, mface++) {
891                         if(tface->flag & TF_SELECT) {
892                                 if(tface->flag & TF_SEL1)
893                                         tface->uv[0][0]= cent[0];
894                                 if(tface->flag & TF_SEL2)
895                                         tface->uv[1][0]= cent[0];
896                                 if(tface->flag & TF_SEL3)
897                                         tface->uv[2][0]= cent[0];
898                                 if(mface->v4 && (tface->flag & TF_SEL4))
899                                         tface->uv[3][0]= cent[0];
900                         }
901                 }
902         }
903
904         if(tool == 'y' || tool == 'w') {
905                 tface= me->tface;
906                 mface= me->mface;
907                 for(a=me->totface; a>0; a--, tface++, mface++) {
908                         if(tface->flag & TF_SELECT) {
909                                 if(tface->flag & TF_SEL1)
910                                         tface->uv[0][1]= cent[1];
911                                 if(tface->flag & TF_SEL2)
912                                         tface->uv[1][1]= cent[1];
913                                 if(tface->flag & TF_SEL3)
914                                         tface->uv[2][1]= cent[1];
915                                 if(mface->v4 && (tface->flag & TF_SEL4))
916                                         tface->uv[3][1]= cent[1];
917                         }
918                 }
919         }
920
921         object_uvs_changed(OBACT);
922 }
923
924 void weld_align_menu_tface_uv(void)
925 {
926         short mode= 0;
927
928         if( is_uv_tface_editing_allowed()==0 ) return;
929
930         mode= pupmenu("Weld/Align%t|Weld%x1|Align X%x2|Align Y%x3|");
931
932         if(mode==-1) return;
933
934         if(mode==1) weld_align_tface_uv('w');
935         else if(mode==2) weld_align_tface_uv('x');
936         else if(mode==3) weld_align_tface_uv('y');
937
938         if(mode==1) BIF_undo_push("Weld UV");
939         else if(mode==2 || mode==3) BIF_undo_push("Align UV");
940 }
941 void select_swap_tface_uv(void)
942 {
943         Mesh *me;
944         TFace *tface;
945         MFace *mface;
946         int a, sel=0;
947         
948         if( is_uv_tface_editing_allowed()==0 ) return;
949         me= get_mesh(OBACT);
950
951         for(a=me->totface, tface= me->tface; a>0; a--, tface++) {
952                 if(tface->flag & TF_SELECT) {   
953                         if(tface->flag & (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4)) {
954                                 sel= 1;
955                                 break;
956                         }
957                 }
958         }
959         
960         mface= me->mface;
961         for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) {
962                 if(tface->flag & TF_SELECT) {
963                         if(mface->v4) {
964                                 if(sel) tface->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
965                                 else tface->flag |= (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
966                         }
967                         else {
968                                 if(sel) tface->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
969                                 else tface->flag |= (TF_SEL1+TF_SEL2+TF_SEL3);
970                         }
971                 }
972         }
973         
974         BIF_undo_push("Select swap UV");
975
976         allqueue(REDRAWIMAGE, 0);
977 }
978
979 static int msel_hit(float *limit, unsigned int *hitarray, unsigned int vertexid, float **uv, float *uv2)
980 {
981         int i;
982         for(i=0; i< 4; i++) {
983                 if(hitarray[i] == vertexid) {
984                         if(G.sima->flag & SI_LOCALSTICKY) {
985                                 if(fabs(uv[i][0]-uv2[0]) < limit[0] &&
986                             fabs(uv[i][1]-uv2[1]) < limit[1])
987                                         return 1;
988                         }
989                         else return 1;
990                 }
991         }
992         return 0;
993 }
994
995 static void find_nearest_tface(TFace **nearesttf, MFace **nearestmf)
996 {
997         Mesh *me;
998         TFace *tf;
999         MFace *mf;
1000         int a, i, nverts, mindist, dist, fcenter[2];
1001         short mval[2], uval[2];
1002
1003         getmouseco_areawin(mval);       
1004
1005         mindist= 0x7FFFFFF;
1006         *nearesttf= NULL;
1007         *nearestmf= NULL;
1008
1009         me= get_mesh(OBACT);
1010         mf= (MFace*)me->mface;
1011         tf= (TFace*)me->tface;
1012
1013         for(a=me->totface; a>0; a--, tf++, mf++) {
1014                 if(tf->flag & TF_SELECT) {
1015
1016                         fcenter[0]= fcenter[1]= 0;
1017                         nverts= mf->v4? 4: 3;
1018                         for(i=0; i<nverts; i++) {
1019                                 uvco_to_areaco_noclip(tf->uv[i], uval);
1020                                 fcenter[0] += uval[0];
1021                                 fcenter[1] += uval[1];
1022                         }
1023
1024                         fcenter[0] /= nverts;
1025                         fcenter[1] /= nverts;
1026
1027                         dist= abs(mval[0]- fcenter[0])+ abs(mval[1]- fcenter[1]);
1028                         if (dist < mindist) {
1029                                 *nearesttf= tf;
1030                                 *nearestmf= mf;
1031                                 mindist= dist;
1032                         }
1033                 }
1034         }
1035 }
1036
1037 static int nearest_uv_between(TFace *tf, int nverts, int id, short *mval, short *uval)
1038 {
1039         float m[3], v1[3], v2[3], c1, c2;
1040         int id1, id2;
1041
1042         id1= (id+nverts-1)%nverts;
1043         id2= (id+nverts+1)%nverts;
1044
1045         m[0] = (float)(mval[0]-uval[0]);
1046         m[1] = (float)(mval[1]-uval[1]);
1047         Vec2Subf(v1, tf->uv[id1], tf->uv[id]);
1048         Vec2Subf(v2, tf->uv[id2], tf->uv[id]);
1049
1050         /* m and v2 on same side of v-v1? */
1051         c1= v1[0]*m[1] - v1[1]*m[0];
1052         c2= v1[0]*v2[1] - v1[1]*v2[0];
1053
1054         if (c1*c2 < 0.0f)
1055                 return 0;
1056
1057         /* m and v1 on same side of v-v2? */
1058         c1= v2[0]*m[1] - v2[1]*m[0];
1059         c2= v2[0]*v1[1] - v2[1]*v1[0];
1060
1061         return (c1*c2 >= 0.0f);
1062 }
1063
1064 static void find_nearest_uv(TFace **nearesttf, unsigned int *nearestv, int *nearestuv)
1065 {
1066         Mesh *me;
1067         TFace *tf;
1068         MFace *mf;
1069         int a, i, nverts, mindist, dist;
1070         short mval[2], uval[2];
1071
1072         getmouseco_areawin(mval);       
1073
1074         mindist= 0x7FFFFFF;
1075         *nearesttf= NULL;
1076
1077         me= get_mesh(OBACT);
1078         mf= (MFace*)me->mface;
1079         tf= (TFace*)me->tface;
1080
1081         for(a=me->totface; a>0; a--, tf++, mf++) {
1082                 if(tf->flag & TF_SELECT) {
1083
1084                         nverts= mf->v4? 4: 3;
1085                         for(i=0; i<nverts; i++) {
1086                                 uvco_to_areaco_noclip(tf->uv[i], uval);
1087                                 dist= abs(mval[0]-uval[0]) + abs(mval[1]-uval[1]);
1088
1089                                 if(tf->flag & TF_SEL_MASK(i))
1090                                         dist += 5;
1091
1092                                 if(dist<=mindist) {
1093                                         if(dist==mindist)
1094                                                 if (!nearest_uv_between(tf, nverts, i, mval, uval))
1095                                                         continue;
1096
1097                                         mindist= dist; 
1098
1099                                         *nearesttf= tf;
1100                                         *nearestuv= i;
1101
1102                                         if (i==0) *nearestv=  mf->v1;
1103                                         else if (i==1) *nearestv=  mf->v2;
1104                                         else if (i==2) *nearestv=  mf->v3;
1105                                         else *nearestv=  mf->v4;
1106                                 }
1107                         }
1108                 }
1109         }
1110 }
1111
1112 void mouse_select_sima(void)
1113 {
1114         Mesh *me;
1115         TFace *tf, *nearesttf;
1116         MFace *mf, *nearestmf;
1117         int a, selectsticky, sticky, actface, nearestuv, i;
1118         unsigned int hitv[4], nearestv;
1119         float *hituv[4], limit[2];
1120         
1121         if( is_uv_tface_editing_allowed()==0 ) return;
1122         me= get_mesh(OBACT);
1123
1124         get_connected_limit_tface_uv(limit);
1125         actface= (G.qual & LR_ALTKEY || G.sima->flag & SI_SELACTFACE);
1126         sticky= (G.qual & LR_CTRLKEY || G.sima->flag & SI_STICKYUVS ||
1127                  G.sima->flag & SI_LOCALSTICKY);
1128
1129         if(actface) {
1130                 find_nearest_tface(&nearesttf, &nearestmf);
1131                 if(nearesttf==NULL)
1132                         return;
1133
1134                 nearesttf->flag |= TF_ACTIVE;
1135
1136                 for (i=0; i<4; i++)
1137                         hituv[i]= nearesttf->uv[i];
1138
1139                 hitv[0]= nearestmf->v1;
1140                 hitv[1]= nearestmf->v2;
1141                 hitv[2]= nearestmf->v3;
1142                 hitv[3]= nearestmf->v4? nearestmf->v4: 0xFFFFFFFF;
1143         }
1144         else {
1145                 find_nearest_uv(&nearesttf, &nearestv, &nearestuv);
1146                 if(nearesttf==NULL)
1147                         return;
1148
1149                 if(sticky) {
1150                         for(i=0; i<4; i++)
1151                                 hitv[i]= 0xFFFFFFFF;
1152                         hitv[nearestuv]= nearestv;
1153                         hituv[nearestuv]= nearesttf->uv[nearestuv];
1154                 }
1155         }
1156
1157         if(G.qual & LR_SHIFTKEY) {
1158                 /* (de)select face */
1159                 if(actface) {
1160                         if(!(~nearesttf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
1161                            && (!nearestmf->v4 || nearesttf->flag & TF_SEL4)) {
1162                                 nearesttf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1163                                 selectsticky= 0;
1164                         }
1165                         else {
1166                                 nearesttf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
1167                                 selectsticky= 1;
1168                         }
1169                 }
1170                 /* (de)select uv node */
1171                 else {
1172                         if(nearesttf->flag & TF_SEL_MASK(nearestuv)) {
1173                                 nearesttf->flag &= ~TF_SEL_MASK(nearestuv);
1174                                 selectsticky= 0;
1175                         }
1176                         else {
1177                                 nearesttf->flag |= TF_SEL_MASK(nearestuv);
1178                                 selectsticky= 1;
1179                         }
1180                 }
1181
1182                 /* (de)select sticky uv nodes */
1183                 if(sticky || actface) {
1184                         mf= (MFace*)me->mface;
1185                         tf= (TFace*)me->tface;
1186                         /* deselect */
1187                         if(selectsticky==0) {
1188                                 for(a=me->totface; a>0; a--, tf++, mf++) {
1189                                         if(!(tf->flag & TF_SELECT)) continue;
1190                                         if(nearesttf && tf!=nearesttf) tf->flag &=~ TF_ACTIVE;
1191                                         if (!sticky) continue;
1192
1193                                         if(msel_hit(limit, hitv, mf->v1, hituv, tf->uv[0]))
1194                                                 tf->flag &= ~TF_SEL1;
1195                                         if(msel_hit(limit, hitv, mf->v2, hituv, tf->uv[1]))
1196                                                 tf->flag &= ~TF_SEL2;
1197                                         if(msel_hit(limit, hitv, mf->v3, hituv, tf->uv[2]))
1198                                                 tf->flag &= ~TF_SEL3;
1199                                         if (mf->v4)
1200                                                 if(msel_hit(limit, hitv, mf->v4, hituv, tf->uv[3]))
1201                                                         tf->flag &= ~TF_SEL4;
1202                                 }
1203                         }
1204                         /* select */
1205                         else {
1206                                 for(a=me->totface; a>0; a--, tf++, mf++) {
1207                                         if(!(tf->flag & TF_SELECT)) continue;
1208                                         if(nearesttf && tf!=nearesttf)
1209                                                 tf->flag &=~ TF_ACTIVE;
1210                                         if (!sticky) continue;
1211
1212                                         if(msel_hit(limit, hitv, mf->v1, hituv, tf->uv[0]))
1213                                                 tf->flag |= TF_SEL1;
1214                                         if(msel_hit(limit, hitv, mf->v2, hituv, tf->uv[1]))
1215                                                 tf->flag |= TF_SEL2;
1216                                         if(msel_hit(limit, hitv, mf->v3, hituv, tf->uv[2]))
1217                                                 tf->flag |= TF_SEL3;
1218                                         if (mf->v4)
1219                                                 if(msel_hit(limit, hitv, mf->v4, hituv, tf->uv[3]))
1220                                                         tf->flag |= TF_SEL4;
1221                                 }
1222                         }
1223                 }
1224         }
1225         else {
1226                 /* select face and deselect other faces */ 
1227                 if(actface) {
1228                         mf= (MFace*)me->mface;
1229                         tf= (TFace*)me->tface;
1230                         for(a=me->totface; a>0; a--, tf++, mf++) {
1231                                 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1232                                 if(nearesttf && tf!=nearesttf)
1233                                         tf->flag &= ~TF_ACTIVE;
1234                         }
1235                         if(nearesttf)
1236                                 nearesttf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1237                 }
1238
1239                 /* deselect uvs, and select sticky uvs */
1240                 mf= (MFace*)me->mface;
1241                 tf= (TFace*)me->tface;
1242                 for(a=me->totface; a>0; a--, tf++, mf++) {
1243                         if(tf->flag & TF_SELECT) {
1244                                 if(!actface) tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1245                                 if(!sticky) continue;
1246
1247                                 if(msel_hit(limit, hitv, mf->v1, hituv, tf->uv[0]))
1248                                         tf->flag |= TF_SEL1;
1249                                 if(msel_hit(limit, hitv, mf->v2, hituv, tf->uv[1]))
1250                                         tf->flag |= TF_SEL2;
1251                                 if(msel_hit(limit, hitv, mf->v3, hituv, tf->uv[2]))
1252                                         tf->flag |= TF_SEL3;
1253                                 if(mf->v4)
1254                                         if(msel_hit(limit, hitv, mf->v4, hituv, tf->uv[3]))
1255                                                 tf->flag |= TF_SEL4;
1256                         }
1257                 }
1258                 
1259                 if(!actface) 
1260                         nearesttf->flag |= TF_SEL_MASK(nearestuv);
1261         }
1262         
1263         force_draw(1);
1264         
1265         BIF_undo_push("Select UV");
1266         std_rmouse_transform(transform_tface_uv);
1267 }
1268
1269 void borderselect_sima(void)
1270 {
1271         Mesh *me;
1272         TFace *tface;
1273         MFace *mface;
1274         rcti rect;
1275         rctf rectf;
1276         int a, val;
1277         short mval[2];
1278
1279         if( is_uv_tface_editing_allowed()==0 ) return;
1280         me= get_mesh(OBACT);
1281
1282         val= get_border(&rect, 3);
1283
1284         if(val) {
1285                 mval[0]= rect.xmin;
1286                 mval[1]= rect.ymin;
1287                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
1288                 mval[0]= rect.xmax;
1289                 mval[1]= rect.ymax;
1290                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
1291
1292                 mface= me->mface;
1293                 for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) {
1294                 
1295                         if(tface->flag & TF_SELECT) {
1296                                 
1297                                 if(BLI_in_rctf(&rectf, (float)tface->uv[0][0], (float)tface->uv[0][1])) {
1298                                         if(val==LEFTMOUSE) tface->flag |= TF_SEL1;
1299                                         else tface->flag &= ~TF_SEL1;
1300                                 }
1301                                 if(BLI_in_rctf(&rectf, (float)tface->uv[1][0], (float)tface->uv[1][1])) {
1302                                         if(val==LEFTMOUSE) tface->flag |= TF_SEL2;
1303                                         else tface->flag &= ~TF_SEL2;
1304                                 }
1305                                 if(BLI_in_rctf(&rectf, (float)tface->uv[2][0], (float)tface->uv[2][1])) {
1306                                         if(val==LEFTMOUSE) tface->flag |= TF_SEL3;
1307                                         else tface->flag &= ~TF_SEL3;
1308                                 }
1309                                 if(mface->v4 && BLI_in_rctf(&rectf, (float)tface->uv[3][0], (float)tface->uv[3][1])) {
1310                                         if(val==LEFTMOUSE) tface->flag |= TF_SEL4;
1311                                         else tface->flag &= ~TF_SEL4;
1312                                 }
1313                         }
1314                                                         
1315                 }
1316                 BIF_undo_push("Border select UV");
1317                 scrarea_queue_winredraw(curarea);
1318         }
1319 }
1320
1321 /** This is an ugly function to set the Tface selection flags depending
1322   * on whether its UV coordinates are inside the normalized 
1323   * area with radius rad and offset offset. These coordinates must be
1324   * normalized to 1.0 
1325   * Just for readability...
1326   */
1327
1328 void sel_uvco_inside_radius(short sel, TFace *tface, int index, float *offset, float *ell, short select_mask)
1329 {
1330         // normalized ellipse: ell[0] = scaleX,
1331         //                        [1] = scaleY
1332
1333         float *uv = tface->uv[index];
1334         float x, y, r2;
1335
1336         x = (uv[0] - offset[0]) * ell[0];
1337         y = (uv[1] - offset[1]) * ell[1];
1338
1339         r2 = x * x + y * y;
1340         if (r2 < 1.0) {
1341                 if (sel == LEFTMOUSE) tface->flag |= select_mask;
1342                 else tface->flag &= ~select_mask;
1343         }
1344 }
1345
1346 // see below:
1347 /** gets image dimensions of the 2D view 'v' */
1348 static void getSpaceImageDimension(SpaceImage *sima, float *xy)
1349 {
1350         Image *img = sima->image;
1351         float z;
1352
1353         z = sima->zoom;
1354
1355         if (img) {
1356                 xy[0] = img->ibuf->x * z;
1357                 xy[1] = img->ibuf->y * z;
1358         } else {
1359                 xy[0] = 256 * z;
1360                 xy[1] = 256 * z;
1361         }
1362 }
1363
1364 /** Callback function called by circle_selectCB to enable 
1365   * brush select in UV editor.
1366   */
1367
1368 void uvedit_selectionCB(short selecting, Object *editobj, short *mval, float rad) 
1369 {
1370         float offset[2];
1371         Mesh *me;
1372         MFace *mface;
1373         TFace *tface;
1374         int i;
1375
1376         float ellipse[2]; // we need to deal with ellipses, as
1377                           // non square textures require for circle
1378                                           // selection. this ellipse is normalized; r = 1.0
1379         
1380         me = get_mesh(editobj);
1381
1382         getSpaceImageDimension(curarea->spacedata.first, ellipse);
1383         ellipse[0] /= rad;
1384         ellipse[1] /= rad;
1385
1386         areamouseco_to_ipoco(G.v2d, mval, &offset[0], &offset[1]);
1387
1388         mface= me->mface;
1389         tface= me->tface;
1390
1391         if (selecting) {
1392                 for(i = 0; i < me->totface; i++) {
1393                         sel_uvco_inside_radius(selecting, tface, 0, offset, ellipse, TF_SEL1);
1394                         sel_uvco_inside_radius(selecting, tface, 1, offset, ellipse, TF_SEL2);
1395                         sel_uvco_inside_radius(selecting, tface, 2, offset, ellipse, TF_SEL3);
1396                         if (mface->v4)
1397                                 sel_uvco_inside_radius(selecting, tface, 3, offset, ellipse, TF_SEL4);
1398                         
1399                         tface++; mface++;
1400
1401                 }
1402
1403                 if(G.f & G_DRAWFACES) { /* full redraw only if necessary */
1404                         draw_sel_circle(0, 0, 0, 0, 0); /* signal */
1405                         force_draw(0);
1406                 }
1407                 else { /* force_draw() is no good here... */
1408                         glDrawBuffer(GL_FRONT);
1409                         draw_tfaces();
1410                         glDrawBuffer(GL_BACK);
1411                 }
1412         }       
1413 }
1414
1415
1416 void mouseco_to_curtile(void)
1417 {
1418         float fx, fy;
1419         short mval[2];
1420         
1421         if( is_uv_tface_editing_allowed()==0) return;
1422
1423         if(G.sima->image && G.sima->image->tpageflag & IMA_TILES) {
1424                 
1425                 G.sima->flag |= SI_EDITTILE;
1426                 
1427                 while(get_mbut()&L_MOUSE) {
1428                         
1429                         calc_image_view(G.sima, 'f');
1430                         
1431                         getmouseco_areawin(mval);
1432                         areamouseco_to_ipoco(G.v2d, mval, &fx, &fy);
1433
1434                         if(fx>=0.0 && fy>=0.0 && fx<1.0 && fy<1.0) {
1435                         
1436                                 fx= (fx)*G.sima->image->xrep;
1437                                 fy= (fy)*G.sima->image->yrep;
1438                                 
1439                                 mval[0]= fx;
1440                                 mval[1]= fy;
1441                                 
1442                                 G.sima->curtile= mval[1]*G.sima->image->xrep + mval[0];
1443                         }
1444
1445                         scrarea_do_windraw(curarea);
1446                         screen_swapbuffers();
1447                 }
1448                 
1449                 G.sima->flag &= ~SI_EDITTILE;
1450
1451                 image_changed(G.sima, 1);
1452
1453                 allqueue(REDRAWVIEW3D, 0);
1454                 scrarea_queue_winredraw(curarea);
1455         }
1456 }
1457
1458 void hide_tface_uv(int swap)
1459 {
1460         Mesh *me;
1461         TFace *tface;
1462         MFace *mface;
1463         int a;
1464
1465         if( is_uv_tface_editing_allowed()==0 ) return;
1466         me= get_mesh(OBACT);
1467
1468         if(swap) {
1469                 mface= me->mface;
1470                 for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) {
1471                         if(tface->flag & TF_SELECT) {
1472                                 if((tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3))==0) {
1473                                         if(!mface->v4)
1474                                                 tface->flag &= ~TF_SELECT;
1475                                         else if(!(tface->flag & TF_SEL4))
1476                                                 tface->flag &= ~TF_SELECT;
1477                                 }
1478                         }
1479                 }
1480         } else {
1481                 mface= me->mface;
1482                 for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) {
1483                         if(tface->flag & TF_SELECT) {
1484                                 if(tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
1485                                                 tface->flag &= ~TF_SELECT;
1486                                 else if(mface->v4 && tface->flag & TF_SEL4)
1487                                                 tface->flag &= ~TF_SELECT;
1488                         }
1489                 }
1490         }
1491
1492         BIF_undo_push("Hide UV");
1493
1494         object_tface_flags_changed(OBACT, 0);
1495 }
1496
1497 void reveal_tface_uv(void)
1498 {
1499         Mesh *me;
1500         TFace *tface;
1501         MFace *mface;
1502         int a;
1503
1504         if( is_uv_tface_editing_allowed()==0 ) return;
1505         me= get_mesh(OBACT);
1506
1507         mface= me->mface;
1508         for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++)
1509                 if(!(tface->flag & TF_HIDE))
1510                         if(!(tface->flag & TF_SELECT))
1511                                 tface->flag |= (TF_SELECT|TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1512         
1513         BIF_undo_push("Reveal UV");
1514
1515         object_tface_flags_changed(OBACT, 0);
1516 }
1517
1518 void stitch_uv_tface(int mode)
1519 {
1520         MFace *mf;
1521         TFace *tf, *tface;
1522         Mesh *me;
1523         int a, b, c, tot, vtot, vtot2;
1524         float newuv[2], limit[2], *uv, *uv1;
1525         struct uvvertsort *sortblock, *sb, *sb1, *sb2;
1526         
1527         if( is_uv_tface_editing_allowed()==0 ) return;
1528
1529         limit[0]= limit[1]= 20.0;
1530         if(mode==1) {
1531                 add_numbut(0, NUM|FLO, "Limit:", 0.1, 1000.0, &limit[0], NULL);
1532                 if (!do_clever_numbuts("Stitch UVs", 1, REDRAW))
1533                         return;
1534         }
1535
1536         if(G.sima->image && G.sima->image->ibuf && G.sima->image->ibuf->x > 0 &&
1537            G.sima->image->ibuf->y > 0) {
1538                 limit[1]= limit[0]/(float)G.sima->image->ibuf->y;
1539                 limit[0]= limit[0]/(float)G.sima->image->ibuf->x;
1540         }
1541         else
1542                 limit[0]= limit[1]= limit[0]/256.0;
1543         
1544         me= get_mesh(OBACT);
1545         tface= (TFace*)me->tface;
1546         
1547         tot= 0;
1548         mf= (MFace*)me->mface;
1549         tf= (TFace*)me->tface;
1550         for(a=me->totface; a>0; a--, tf++, mf++) {
1551                 if((tf->flag & TF_SELECT)) {
1552                         if(tf->flag & TF_SEL1) tot++;
1553                         if(tf->flag & TF_SEL2) tot++;
1554                         if(tf->flag & TF_SEL3) tot++;
1555                         if(mf->v4 && tf->flag & TF_SEL4) tot++; 
1556                 }
1557         }
1558         if(tot==0) return;
1559
1560         sb= sortblock= MEM_callocN(sizeof(struct uvvertsort)*tot,"sortstitchuv");
1561
1562         mf= (MFace*)me->mface;
1563         tf= (TFace*)me->tface;
1564         for(a=0; a<me->totface; a++, tf++, mf++) {
1565                 if((tf->flag & TF_SELECT)) {
1566                         if(tf->flag & TF_SEL1) {
1567                                 sb->v= mf->v1;
1568                                 sb->f= a;
1569                                 sb->tf_sel= 0;
1570                                 sb++;
1571                         }
1572                         if(tf->flag & TF_SEL2) {
1573                                 sb->v= mf->v2;
1574                                 sb->f= a;
1575                                 sb->tf_sel= 1;
1576                                 sb++;
1577                         }
1578                         if(tf->flag & TF_SEL3) {
1579                                 sb->v= mf->v3;
1580                                 sb->f= a;
1581                                 sb->tf_sel= 2;
1582                                 sb++;
1583                         }
1584                         if(mf->v4 && tf->flag & TF_SEL4) {
1585                                 sb->v= mf->v4;
1586                                 sb->f= a;
1587                                 sb->tf_sel= 3;
1588                                 sb++;
1589                         }
1590                 }
1591         }
1592         
1593         /* sort by vertex */
1594         qsort(sortblock, tot, sizeof(struct uvvertsort), compuvvert);
1595
1596         if(mode==0) {
1597                 for (a=0, sb=sortblock; a<tot; a+=vtot, sb+=vtot) {
1598                         newuv[0]= 0; newuv[1]= 0;
1599                         vtot= 0;
1600
1601                         for (b=a, sb1=sb; b<tot && sb1->v==sb->v; b++, sb1++) {
1602                                 newuv[0] += tface[sb1->f].uv[sb1->tf_sel][0];
1603                                 newuv[1] += tface[sb1->f].uv[sb1->tf_sel][1];
1604                                 vtot++;
1605                         }
1606
1607                         newuv[0] /= vtot; newuv[1] /= vtot;
1608
1609                         for (b=a, sb1=sb; b<a+vtot; b++, sb1++) {
1610                                 tface[sb1->f].uv[sb1->tf_sel][0]= newuv[0];
1611                                 tface[sb1->f].uv[sb1->tf_sel][1]= newuv[1];
1612                         }
1613                 }
1614         } else if(mode==1) {
1615                 for (a=0, sb=sortblock; a<tot; a+=vtot, sb+=vtot) {
1616                         vtot= 0;
1617                         for (b=a, sb1=sb; b<tot && sb1->v==sb->v; b++, sb1++)
1618                                 vtot++;
1619
1620                         for (b=a, sb1=sb; b<a+vtot; b++, sb1++) {
1621                                 if(sb1->flag & 2) continue;
1622
1623                                 newuv[0]= 0; newuv[1]= 0;
1624                                 vtot2 = 0;
1625
1626                                 for (c=b, sb2=sb1; c<a+vtot; c++, sb2++) {
1627                                         uv = tface[sb2->f].uv[sb2->tf_sel];
1628                                         uv1 = tface[sb1->f].uv[sb1->tf_sel];
1629                                         if (fabs(uv[0]-uv1[0]) < limit[0] &&
1630                                             fabs(uv[1]-uv1[1]) < limit[1]) {
1631                                                 newuv[0] += uv[0];
1632                                                 newuv[1] += uv[1];
1633                                                 sb2->flag |= 2;
1634                                                 sb2->flag |= 4;
1635                                                 vtot2++;
1636                                         }
1637                                 }
1638
1639                                 newuv[0] /= vtot2; newuv[1] /= vtot2;
1640
1641                                 for (c=b, sb2=sb1; c<a+vtot; c++, sb2++) {
1642                                         if(sb2->flag & 4) {
1643                                                 tface[sb2->f].uv[sb2->tf_sel][0]= newuv[0];
1644                                                 tface[sb2->f].uv[sb2->tf_sel][1]= newuv[1];
1645                                                 sb2->flag &= ~4;
1646                                         }
1647                                 }
1648                         }
1649                 }
1650         }
1651         MEM_freeN(sortblock);
1652
1653         if(G.sima->flag & SI_BE_SQUARE) be_square_tface_uv(me);
1654         if(G.sima->flag & SI_CLIP_UV) tface_do_clip();
1655
1656         BIF_undo_push("Stitch UV");
1657
1658         object_uvs_changed(OBACT);
1659 }
1660
1661 void select_linked_tface_uv(int mode)
1662 {
1663         MFace *mf;
1664         TFace *tface, *tf, *nearesttf=NULL;
1665         Mesh *me;
1666         char sel, *linkflag;
1667         int a, b, c, tot, vtot, nearestv, nearestuv, i, nverts;
1668         float limit[2], *uv, *uv1;
1669         struct uvvertsort *sortblock, *sb, *sb1, *sb2;
1670         
1671         if( is_uv_tface_editing_allowed()==0 ) return;
1672
1673         me= get_mesh(OBACT);
1674         get_connected_limit_tface_uv(limit);
1675
1676         tot= 0;
1677         mf= (MFace*)me->mface;
1678         tf= (TFace*)me->tface;
1679         for(a=me->totface; a>0; a--, tf++, mf++)
1680                 if(tf->flag & TF_SELECT)
1681                         tot += mf->v4? 4: 3;
1682
1683         if(tot==0) return;
1684
1685         if (mode!=2) {
1686                 find_nearest_uv(&nearesttf, &nearestv, &nearestuv);
1687
1688                 if(nearesttf==NULL)
1689                         return;
1690         }
1691         else {
1692                 nearesttf= NULL;
1693                 nearestuv= 0;
1694         }
1695
1696         sb= sortblock= MEM_callocN(sizeof(struct uvvertsort)*tot, "sortsellinkuv");
1697         linkflag= MEM_callocN(sizeof(char)*me->totface, "linkflaguv");
1698
1699         mf= (MFace*)me->mface;
1700         tf= (TFace*)me->tface;
1701         for(a=0; a<me->totface; a++, tf++, mf++) {
1702                 if(!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT)) {
1703                         sel= 0;
1704                         sb1= sb;
1705                         nverts= mf->v4? 4: 3;
1706                         for(i=0; i<nverts; i++) {
1707                                 if(tf->flag & TF_SEL_MASK(i))
1708                                         sel= 1;
1709                                 sb->f= a;
1710                                 sb->tf_sel= i;
1711                                 sb++;
1712                         }
1713
1714                         if(nearesttf==tf || ((sel && mode==2)))
1715                                 linkflag[a] = 1;
1716
1717                         (sb1)->v= mf->v1;
1718                         (sb1+1)->v= mf->v2;
1719                         (sb1+2)->v= mf->v3;
1720                         if(mf->v4) (sb1+3)->v= mf->v4;
1721                 }
1722         }
1723         
1724         /* sort by vertex */
1725         qsort(sortblock, tot, sizeof(struct uvvertsort), compuvvert);
1726
1727         tface= (TFace*)me->tface;
1728         sel= 1;
1729         while(sel) {
1730                 sel= 0;
1731
1732                 /* select all tex vertices that are near a selected tex vertex */
1733                 for (a=0, sb=sortblock; a<tot; a+=vtot, sb+=vtot) {
1734                         vtot= 0;
1735                         for (b=a, sb1=sb; b<tot && sb1->v==sb->v; b++, sb1++)
1736                                 vtot++;
1737                         for (b=a, sb1=sb; b<a+vtot; b++, sb1++) {
1738                                 if(linkflag[sb1->f]) continue;
1739
1740                                 for (c=a, sb2=sb; c<a+vtot; c++, sb2++) {
1741                                         if(!(linkflag[sb2->f])) continue;
1742                                         
1743                                         uv = tface[sb2->f].uv[sb2->tf_sel];
1744                                         uv1 = tface[sb1->f].uv[sb1->tf_sel];
1745                                         if (fabs(uv[0]-uv1[0]) < limit[0] &&
1746                                             fabs(uv[1]-uv1[1]) < limit[1]) {
1747                                                 linkflag[sb1->f] = 1;
1748                                                 sel= 1;
1749                                                 break;
1750                                         }
1751                                 }
1752                         }
1753                 }
1754         }
1755
1756         if(mode==0 || mode==2) {
1757                 for(a=0, tf=tface; a<me->totface; a++, tf++)
1758                         if(linkflag[a])
1759                                 tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1760                         else
1761                                 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1762         }
1763         else if(mode==1) {
1764                 for(a=0, tf=tface; a<me->totface; a++, tf++) {
1765                         if(linkflag[a]) {
1766                                 if (mf->v4) {
1767                                         if((tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)))
1768                                                 break;
1769                                 }
1770                                 else if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
1771                                         break;
1772                         }
1773                 }
1774
1775                 if (a<me->totface) {
1776                         for(a=0, tf=tface; a<me->totface; a++, tf++)
1777                                 if(linkflag[a])
1778                                         tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1779                 }
1780                 else {
1781                         for(a=0, tf=tface; a<me->totface; a++, tf++)
1782                                 if(linkflag[a])
1783                                         tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1784                 }
1785         }
1786         
1787         MEM_freeN(sortblock);
1788         MEM_freeN(linkflag);
1789
1790         BIF_undo_push("Select linked UV");
1791         scrarea_queue_winredraw(curarea);
1792 }
1793
1794 void unlink_selection(void)
1795 {
1796         Mesh *me;
1797         TFace *tface;
1798         MFace *mface;
1799         int a;
1800
1801         if( is_uv_tface_editing_allowed()==0 ) return;
1802         me= get_mesh(OBACT);
1803
1804         mface= me->mface;
1805         for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) {
1806                 if(tface->flag & TF_SELECT) {
1807                         if(mface->v4) {
1808                                 if(~tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4))
1809                                         tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1810                         } else {
1811                                 if(~tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
1812                                         tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3);
1813                         }
1814                 }
1815         }
1816         
1817         BIF_undo_push("Unlink UV selection");
1818         scrarea_queue_winredraw(curarea);
1819 }
1820
1821 void toggle_uv_select(int mode)
1822 {
1823         switch(mode){
1824         case 'f':
1825                 G.sima->flag ^= SI_SELACTFACE;
1826                 break;
1827         case 's':
1828                 G.sima->flag ^= SI_STICKYUVS; 
1829                 if (G.sima->flag & SI_STICKYUVS) G.sima->flag &= ~SI_LOCALSTICKY;
1830                 break;
1831         case 'l': 
1832                  G.sima->flag ^= SI_LOCALSTICKY;
1833                  if (G.sima->flag & SI_LOCALSTICKY) G.sima->flag &= ~SI_STICKYUVS;
1834                 break;
1835         case 'o':
1836                 G.sima->flag &= ~SI_STICKYUVS; 
1837                 G.sima->flag &= ~SI_LOCALSTICKY;
1838                 break;
1839         }
1840         allqueue(REDRAWIMAGE, 0);
1841 }
1842
1843 void pin_tface_uv(int mode)
1844 {
1845         Mesh *me;
1846         TFace *tface;
1847         MFace *mface;
1848         int a;
1849         
1850         if( is_uv_tface_editing_allowed()==0 ) return;
1851         me= get_mesh(OBACT);
1852         
1853         mface= me->mface;
1854         tface= me->tface;
1855         for(a=me->totface; a>0; a--, tface++, mface++) {
1856                 if(tface->flag & TF_SELECT) {
1857                         if(mode ==1){
1858                                 if(tface->flag & TF_SEL1) tface->unwrap |= TF_PIN1;
1859                                 if(tface->flag & TF_SEL2) tface->unwrap |= TF_PIN2;
1860                                 if(tface->flag & TF_SEL3) tface->unwrap |= TF_PIN3;
1861                                 if(mface->v4)
1862                                         if(tface->flag & TF_SEL4) tface->unwrap |= TF_PIN4;
1863                         }
1864                         else if (mode ==0){
1865                                 if(tface->flag & TF_SEL1) tface->unwrap &= ~TF_PIN1;
1866                                 if(tface->flag & TF_SEL2) tface->unwrap &= ~TF_PIN2;
1867                                 if(tface->flag & TF_SEL3) tface->unwrap &= ~TF_PIN3;
1868                                 if(mface->v4)
1869                                 if(tface->flag & TF_SEL4) tface->unwrap &= ~TF_PIN4;
1870                         }
1871                 }
1872         }
1873         
1874         BIF_undo_push("Pin UV");
1875         scrarea_queue_winredraw(curarea);
1876 }
1877
1878 int minmax_tface_uv(float *min, float *max)
1879 {
1880         Mesh *me;
1881         TFace *tf;
1882         MFace *mf;
1883         int a, sel;
1884
1885         if( is_uv_tface_editing_allowed()==0 ) return 0;
1886         me= get_mesh(OBACT);
1887
1888         INIT_MINMAX2(min, max);
1889
1890         sel= 0;
1891         mf= (MFace*)me->mface;
1892         tf= (TFace*)me->tface;
1893         for(a=me->totface; a>0; a--, tf++, mf++) {
1894                 if(tf->flag & TF_HIDE);
1895                 else if(tf->flag & TF_SELECT) {
1896
1897                         if (tf->flag & TF_SEL1) {
1898                                 DO_MINMAX2(tf->uv[0], min, max);
1899                         }
1900                         if (tf->flag & TF_SEL2) {
1901                                 DO_MINMAX2(tf->uv[1], min, max);
1902                         }
1903                         if (tf->flag & TF_SEL3) {
1904                                 DO_MINMAX2(tf->uv[2], min, max);
1905                         }
1906                         if (mf->v4 && tf->flag & TF_SEL4) {
1907                                 DO_MINMAX2(tf->uv[3], min, max);
1908                         }
1909
1910                         sel = 1;
1911                 }
1912         }
1913
1914         return sel;
1915 }
1916