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