Final merge of HEAD (bf-blender) into the orange branch.
[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_colortools.h"
63 #include "BKE_depsgraph.h"
64 #include "BKE_global.h"
65 #include "BKE_mesh.h"
66 #include "BKE_displist.h"
67 #include "BKE_object.h"
68 #include "BKE_utildefines.h"
69
70 #include "BIF_gl.h"
71 #include "BIF_interface.h"
72 #include "BIF_screen.h"
73 #include "BIF_drawimage.h"
74 #include "BIF_editview.h"
75 #include "BIF_space.h"
76 #include "BIF_editsima.h"
77 #include "BIF_toolbox.h"
78 #include "BIF_transform.h"
79 #include "BIF_mywindow.h"
80
81 #include "BSE_drawipo.h"
82 #include "BSE_edit.h"
83 #include "BSE_trans_types.h"
84
85 #include "BDR_editobject.h"
86 #include "BDR_unwrapper.h"
87
88 #include "BMF_Api.h"
89
90 #include "blendef.h"
91 #include "mydevice.h"
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 void object_uvs_changed(Object *ob)
99 {
100         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
101
102         allqueue(REDRAWVIEW3D, 0);
103         allqueue(REDRAWIMAGE, 0);
104 }
105
106 void object_tface_flags_changed(Object *ob, int updateButtons)
107 {
108         if (updateButtons) allqueue(REDRAWBUTSEDIT, 0);
109         allqueue(REDRAWVIEW3D, 0);
110         allqueue(REDRAWIMAGE, 0);
111 }
112
113 int is_uv_tface_editing_allowed_silent(void)
114 {
115         Mesh *me;
116
117         if(G.obedit) return 0;
118         if(G.sima->mode!=SI_TEXTURE) return 0;
119         if(!(G.f & G_FACESELECT)) return 0;  
120         me= get_mesh(OBACT);
121         if(me==0 || me->tface==0) return 0;
122         
123         return 1;
124 }
125
126 int is_uv_tface_editing_allowed(void)
127 {
128         if(G.obedit) error("Unable to perform action in Edit Mode");
129
130         return is_uv_tface_editing_allowed_silent();
131 }
132
133 void get_connected_limit_tface_uv(float *limit)
134 {
135         if(G.sima->image && G.sima->image->ibuf && G.sima->image->ibuf->x > 0 &&
136            G.sima->image->ibuf->y > 0) {
137                 limit[0]= 0.05/(float)G.sima->image->ibuf->x;
138                 limit[1]= 0.05/(float)G.sima->image->ibuf->y;
139         }
140         else
141                 limit[0]= limit[1]= 0.05/256.0;
142 }
143
144 void clever_numbuts_sima(void)
145 {
146         float ocent[2], cent[2]= {0.0, 0.0};
147         int imx, imy;
148         int i, nactive= 0;
149         Mesh *me;
150         
151         if( is_uv_tface_editing_allowed()==0 ) return;
152         me= get_mesh(OBACT);
153         
154         if (G.sima->image && G.sima->image->ibuf) {
155                 imx= G.sima->image->ibuf->x;
156                 imy= G.sima->image->ibuf->y;
157         } else
158                 imx= imy= 256;
159         
160         for (i=0; i<me->totface; i++) {
161                 MFace *mf= &((MFace*) me->mface)[i];
162                 TFace *tf= &((TFace*) me->tface)[i];
163                 
164                 if (!(tf->flag & TF_SELECT))
165                         continue;
166                 
167                 if (tf->flag & TF_SEL1) {
168                         cent[0]+= tf->uv[0][0];
169                         cent[1]+= tf->uv[0][1];
170                         nactive++;
171                 }
172                 if (tf->flag & TF_SEL2) {
173                         cent[0]+= tf->uv[1][0];
174                         cent[1]+= tf->uv[1][1];
175                         nactive++;
176                 }
177                 if (tf->flag & TF_SEL3) {
178                         cent[0]+= tf->uv[2][0];
179                         cent[1]+= tf->uv[2][1];
180                         nactive++;
181                 }
182                 if (mf->v4 && (tf->flag & TF_SEL4)) {
183                         cent[0]+= tf->uv[3][0];
184                         cent[1]+= tf->uv[3][1];
185                         nactive++;
186                 }
187         }
188         
189         if (nactive) {
190                 cent[0]= (cent[0]*imx)/nactive;
191                 cent[1]= (cent[1]*imy)/nactive;
192
193                 add_numbut(0, NUM|FLO, "LocX:", -imx*20, imx*20, &cent[0], NULL);
194                 add_numbut(1, NUM|FLO, "LocY:", -imy*20, imy*20, &cent[1], NULL);
195                 
196                 ocent[0]= cent[0];
197                 ocent[1]= cent[1];
198                 if (do_clever_numbuts((nactive==1)?"Active Vertex":"Selected Center", 2, REDRAW)) {
199                         float delta[2];
200                         
201                         delta[0]= (cent[0]-ocent[0])/imx;
202                         delta[1]= (cent[1]-ocent[1])/imy;
203
204                         for (i=0; i<me->totface; i++) {
205                                 MFace *mf= &((MFace*) me->mface)[i];
206                                 TFace *tf= &((TFace*) me->tface)[i];
207                         
208                                 if (!(tf->flag & TF_SELECT))
209                                         continue;
210                         
211                                 if (tf->flag & TF_SEL1) {
212                                         tf->uv[0][0]+= delta[0];
213                                         tf->uv[0][1]+= delta[1];
214                                 }
215                                 if (tf->flag & TF_SEL2) {
216                                         tf->uv[1][0]+= delta[0];
217                                         tf->uv[1][1]+= delta[1];
218                                 }
219                                 if (tf->flag & TF_SEL3) {
220                                         tf->uv[2][0]+= delta[0];
221                                         tf->uv[2][1]+= delta[1];
222                                 }
223                                 if (mf->v4 && (tf->flag & TF_SEL4)) {
224                                         tf->uv[3][0]+= delta[0];
225                                         tf->uv[3][1]+= delta[1];
226                                 }
227                         }
228                         
229                         object_uvs_changed(OBACT);
230                 }
231         }
232 }
233
234 void be_square_tface_uv(Mesh *me)
235 {
236         TFace *tface;
237         MFace *mface;
238         int a;
239         
240         /* if 1 vertex selected: doit (with the selected vertex) */
241         mface= (MFace*)me->mface;
242         tface= (TFace*)me->tface;
243         for(a=me->totface; a>0; a--, tface++, mface++) {
244                 if(mface->v4) {
245                         if(tface->flag & TF_SELECT) {
246                                 if(tface->flag & TF_SEL1) {
247                                         if( tface->uv[1][0] == tface->uv[2][0] ) {
248                                                 tface->uv[1][1]= tface->uv[0][1];
249                                                 tface->uv[3][0]= tface->uv[0][0];
250                                         }
251                                         else {  
252                                                 tface->uv[1][0]= tface->uv[0][0];
253                                                 tface->uv[3][1]= tface->uv[0][1];
254                                         }
255                                         
256                                 }
257                                 if(tface->flag & TF_SEL2) {
258                                         if( tface->uv[2][1] == tface->uv[3][1] ) {
259                                                 tface->uv[2][0]= tface->uv[1][0];
260                                                 tface->uv[0][1]= tface->uv[1][1];
261                                         }
262                                         else {
263                                                 tface->uv[2][1]= tface->uv[1][1];
264                                                 tface->uv[0][0]= tface->uv[1][0];
265                                         }
266
267                                 }
268                                 if(tface->flag & TF_SEL3) {
269                                         if( tface->uv[3][0] == tface->uv[0][0] ) {
270                                                 tface->uv[3][1]= tface->uv[2][1];
271                                                 tface->uv[1][0]= tface->uv[2][0];
272                                         }
273                                         else {
274                                                 tface->uv[3][0]= tface->uv[2][0];
275                                                 tface->uv[1][1]= tface->uv[2][1];
276                                         }
277                                 }
278                                 if(tface->flag & TF_SEL4) {
279                                         if( tface->uv[0][1] == tface->uv[1][1] ) {
280                                                 tface->uv[0][0]= tface->uv[3][0];
281                                                 tface->uv[2][1]= tface->uv[3][1];
282                                         }
283                                         else  {
284                                                 tface->uv[0][1]= tface->uv[3][1];
285                                                 tface->uv[2][0]= tface->uv[3][0];
286                                         }
287
288                                 }
289                         }
290                 }
291         }
292 }
293
294 void transform_aspect_ratio_tface_uv(float *aspx, float *aspy)
295 {
296         int w, h;
297
298         transform_width_height_tface_uv(&w, &h);
299         *aspx= (float)w/256.0f;
300         *aspy= (float)h/256.0f;
301 }
302
303 void transform_width_height_tface_uv(int *width, int *height)
304 {
305         if(G.sima->image && G.sima->image->ibuf) {
306                 *width= G.sima->image->ibuf->x;
307                 *height= G.sima->image->ibuf->y;
308         }
309         else {
310                 *width= 256;
311                 *height= 256;
312         }
313 }
314
315 void mirror_tface_uv(char mirroraxis)
316 {
317         if (mirroraxis == 'x')
318                 Mirror(1); /* global x */
319         else if (mirroraxis == 'y')
320                 Mirror(2); /* global y */
321 }
322
323 void mirrormenu_tface_uv(void)
324 {
325         short mode= 0;
326
327         if( is_uv_tface_editing_allowed()==0 ) return;
328
329         mode= pupmenu("Mirror%t|X Axis%x1|Y Axis%x2|");
330
331         if(mode==-1) return;
332
333         if(mode==1) mirror_tface_uv('x');
334         else if(mode==2) mirror_tface_uv('y');
335
336         BIF_undo_push("Mirror UV");
337 }
338
339 void weld_align_tface_uv(char tool)
340 {
341         MFace *mface;
342         TFace *tface;
343         Mesh *me;
344         float min[2], max[2], cent[2];
345         int a;
346         
347         if( is_uv_tface_editing_allowed()==0 ) return;
348         me= get_mesh(OBACT);
349
350         if (!minmax_tface_uv(min, max))
351                 return;
352
353         cent[0]= (min[0]+max[0])/2.0;
354         cent[1]= (min[1]+max[1])/2.0;
355
356         if(tool == 'x' || tool == 'w') {
357                 tface= me->tface;
358                 mface= me->mface;
359                 for(a=me->totface; a>0; a--, tface++, mface++) {
360                         if(tface->flag & TF_SELECT) {
361                                 if(tface->flag & TF_SEL1)
362                                         tface->uv[0][0]= cent[0];
363                                 if(tface->flag & TF_SEL2)
364                                         tface->uv[1][0]= cent[0];
365                                 if(tface->flag & TF_SEL3)
366                                         tface->uv[2][0]= cent[0];
367                                 if(mface->v4 && (tface->flag & TF_SEL4))
368                                         tface->uv[3][0]= cent[0];
369                         }
370                 }
371         }
372
373         if(tool == 'y' || tool == 'w') {
374                 tface= me->tface;
375                 mface= me->mface;
376                 for(a=me->totface; a>0; a--, tface++, mface++) {
377                         if(tface->flag & TF_SELECT) {
378                                 if(tface->flag & TF_SEL1)
379                                         tface->uv[0][1]= cent[1];
380                                 if(tface->flag & TF_SEL2)
381                                         tface->uv[1][1]= cent[1];
382                                 if(tface->flag & TF_SEL3)
383                                         tface->uv[2][1]= cent[1];
384                                 if(mface->v4 && (tface->flag & TF_SEL4))
385                                         tface->uv[3][1]= cent[1];
386                         }
387                 }
388         }
389
390         object_uvs_changed(OBACT);
391 }
392
393 void weld_align_menu_tface_uv(void)
394 {
395         short mode= 0;
396
397         if( is_uv_tface_editing_allowed()==0 ) return;
398
399         mode= pupmenu("Weld/Align%t|Weld%x1|Align X%x2|Align Y%x3|");
400
401         if(mode==-1) return;
402
403         if(mode==1) weld_align_tface_uv('w');
404         else if(mode==2) weld_align_tface_uv('x');
405         else if(mode==3) weld_align_tface_uv('y');
406
407         if(mode==1) BIF_undo_push("Weld UV");
408         else if(mode==2 || mode==3) BIF_undo_push("Align UV");
409 }
410
411 void select_swap_tface_uv(void)
412 {
413         Mesh *me;
414         TFace *tface;
415         MFace *mface;
416         int a, sel=0;
417         
418         if( is_uv_tface_editing_allowed()==0 ) return;
419         me= get_mesh(OBACT);
420
421         for(a=me->totface, tface= me->tface; a>0; a--, tface++) {
422                 if(tface->flag & TF_SELECT) {   
423                         if(tface->flag & (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4)) {
424                                 sel= 1;
425                                 break;
426                         }
427                 }
428         }
429         
430         mface= me->mface;
431         for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) {
432                 if(tface->flag & TF_SELECT) {
433                         if(mface->v4) {
434                                 if(sel) tface->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
435                                 else tface->flag |= (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
436                         }
437                         else {
438                                 if(sel) tface->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
439                                 else tface->flag |= (TF_SEL1+TF_SEL2+TF_SEL3);
440                         }
441                 }
442         }
443         
444         BIF_undo_push("Select swap UV");
445
446         allqueue(REDRAWIMAGE, 0);
447 }
448
449 static int msel_hit(float *limit, unsigned int *hitarray, unsigned int vertexid, float **uv, float *uv2)
450 {
451         int i;
452         for(i=0; i< 4; i++) {
453                 if(hitarray[i] == vertexid) {
454                         if(G.sima->flag & SI_LOCALSTICKY) {
455                                 if(fabs(uv[i][0]-uv2[0]) < limit[0] &&
456                             fabs(uv[i][1]-uv2[1]) < limit[1])
457                                         return 1;
458                         }
459                         else return 1;
460                 }
461         }
462         return 0;
463 }
464
465 static void find_nearest_tface(TFace **nearesttf, MFace **nearestmf)
466 {
467         Mesh *me;
468         TFace *tf;
469         MFace *mf;
470         int a, i, nverts, mindist, dist, fcenter[2], uval[2];
471         short mval[2];
472
473         getmouseco_areawin(mval);       
474
475         mindist= 0x7FFFFFF;
476         *nearesttf= NULL;
477         *nearestmf= NULL;
478
479         me= get_mesh(OBACT);
480         mf= (MFace*)me->mface;
481         tf= (TFace*)me->tface;
482
483         for(a=me->totface; a>0; a--, tf++, mf++) {
484                 if(tf->flag & TF_SELECT) {
485
486                         fcenter[0]= fcenter[1]= 0;
487                         nverts= mf->v4? 4: 3;
488                         for(i=0; i<nverts; i++) {
489                                 uvco_to_areaco_noclip(tf->uv[i], uval);
490                                 fcenter[0] += uval[0];
491                                 fcenter[1] += uval[1];
492                         }
493
494                         fcenter[0] /= nverts;
495                         fcenter[1] /= nverts;
496
497                         dist= abs(mval[0]- fcenter[0])+ abs(mval[1]- fcenter[1]);
498                         if (dist < mindist) {
499                                 *nearesttf= tf;
500                                 *nearestmf= mf;
501                                 mindist= dist;
502                         }
503                 }
504         }
505 }
506
507 static int nearest_uv_between(TFace *tf, int nverts, int id, short *mval, int *uval)
508 {
509         float m[3], v1[3], v2[3], c1, c2;
510         int id1, id2;
511
512         id1= (id+nverts-1)%nverts;
513         id2= (id+nverts+1)%nverts;
514
515         m[0] = (float)(mval[0]-uval[0]);
516         m[1] = (float)(mval[1]-uval[1]);
517         Vec2Subf(v1, tf->uv[id1], tf->uv[id]);
518         Vec2Subf(v2, tf->uv[id2], tf->uv[id]);
519
520         /* m and v2 on same side of v-v1? */
521         c1= v1[0]*m[1] - v1[1]*m[0];
522         c2= v1[0]*v2[1] - v1[1]*v2[0];
523
524         if (c1*c2 < 0.0f)
525                 return 0;
526
527         /* m and v1 on same side of v-v2? */
528         c1= v2[0]*m[1] - v2[1]*m[0];
529         c2= v2[0]*v1[1] - v2[1]*v1[0];
530
531         return (c1*c2 >= 0.0f);
532 }
533
534 static void find_nearest_uv(TFace **nearesttf, unsigned int *nearestv, int *nearestuv)
535 {
536         Mesh *me;
537         TFace *tf;
538         MFace *mf;
539         int a, i, nverts, mindist, dist, uval[2];
540         short mval[2];
541
542         getmouseco_areawin(mval);       
543
544         mindist= 0x7FFFFFF;
545         *nearesttf= NULL;
546
547         me= get_mesh(OBACT);
548         mf= (MFace*)me->mface;
549         tf= (TFace*)me->tface;
550
551         for(a=me->totface; a>0; a--, tf++, mf++) {
552                 if(tf->flag & TF_SELECT) {
553
554                         nverts= mf->v4? 4: 3;
555                         for(i=0; i<nverts; i++) {
556                                 uvco_to_areaco_noclip(tf->uv[i], uval);
557                                 dist= abs(mval[0]-uval[0]) + abs(mval[1]-uval[1]);
558
559                                 if(tf->flag & TF_SEL_MASK(i))
560                                         dist += 5;
561
562                                 if(dist<=mindist) {
563                                         if(dist==mindist)
564                                                 if (!nearest_uv_between(tf, nverts, i, mval, uval))
565                                                         continue;
566
567                                         mindist= dist; 
568
569                                         *nearesttf= tf;
570                                         *nearestuv= i;
571
572                                         if (i==0) *nearestv=  mf->v1;
573                                         else if (i==1) *nearestv=  mf->v2;
574                                         else if (i==2) *nearestv=  mf->v3;
575                                         else *nearestv=  mf->v4;
576                                 }
577                         }
578                 }
579         }
580 }
581
582 void mouse_select_sima(void)
583 {
584         Mesh *me;
585         TFace *tf, *nearesttf;
586         MFace *mf, *nearestmf=NULL;
587         int a, selectsticky, sticky, actface, nearestuv, i;
588         unsigned int hitv[4], nearestv;
589         float *hituv[4], limit[2];
590         
591         if( is_uv_tface_editing_allowed()==0 ) return;
592         me= get_mesh(OBACT);
593
594         get_connected_limit_tface_uv(limit);
595         actface= (G.qual & LR_ALTKEY || G.sima->flag & SI_SELACTFACE);
596         sticky= (G.qual & LR_CTRLKEY || G.sima->flag & SI_STICKYUVS ||
597                  G.sima->flag & SI_LOCALSTICKY);
598
599         if(actface) {
600                 find_nearest_tface(&nearesttf, &nearestmf);
601                 if(nearesttf==NULL)
602                         return;
603
604                 nearesttf->flag |= TF_ACTIVE;
605
606                 for (i=0; i<4; i++)
607                         hituv[i]= nearesttf->uv[i];
608
609                 hitv[0]= nearestmf->v1;
610                 hitv[1]= nearestmf->v2;
611                 hitv[2]= nearestmf->v3;
612                 hitv[3]= nearestmf->v4? nearestmf->v4: 0xFFFFFFFF;
613         }
614         else {
615                 find_nearest_uv(&nearesttf, &nearestv, &nearestuv);
616                 if(nearesttf==NULL)
617                         return;
618
619                 if(sticky) {
620                         for(i=0; i<4; i++)
621                                 hitv[i]= 0xFFFFFFFF;
622                         hitv[nearestuv]= nearestv;
623                         hituv[nearestuv]= nearesttf->uv[nearestuv];
624                 }
625         }
626
627         if(G.qual & LR_SHIFTKEY) {
628                 /* (de)select face */
629                 if(actface) {
630                         if(!(~nearesttf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
631                            && (!nearestmf->v4 || nearesttf->flag & TF_SEL4)) {
632                                 nearesttf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
633                                 selectsticky= 0;
634                         }
635                         else {
636                                 nearesttf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
637                                 selectsticky= 1;
638                         }
639                 }
640                 /* (de)select uv node */
641                 else {
642                         if(nearesttf->flag & TF_SEL_MASK(nearestuv)) {
643                                 nearesttf->flag &= ~TF_SEL_MASK(nearestuv);
644                                 selectsticky= 0;
645                         }
646                         else {
647                                 nearesttf->flag |= TF_SEL_MASK(nearestuv);
648                                 selectsticky= 1;
649                         }
650                 }
651
652                 /* (de)select sticky uv nodes */
653                 if(sticky || actface) {
654                         mf= (MFace*)me->mface;
655                         tf= (TFace*)me->tface;
656                         /* deselect */
657                         if(selectsticky==0) {
658                                 for(a=me->totface; a>0; a--, tf++, mf++) {
659                                         if(!(tf->flag & TF_SELECT)) continue;
660                                         if(nearesttf && tf!=nearesttf) tf->flag &=~ TF_ACTIVE;
661                                         if (!sticky) continue;
662
663                                         if(msel_hit(limit, hitv, mf->v1, hituv, tf->uv[0]))
664                                                 tf->flag &= ~TF_SEL1;
665                                         if(msel_hit(limit, hitv, mf->v2, hituv, tf->uv[1]))
666                                                 tf->flag &= ~TF_SEL2;
667                                         if(msel_hit(limit, hitv, mf->v3, hituv, tf->uv[2]))
668                                                 tf->flag &= ~TF_SEL3;
669                                         if (mf->v4)
670                                                 if(msel_hit(limit, hitv, mf->v4, hituv, tf->uv[3]))
671                                                         tf->flag &= ~TF_SEL4;
672                                 }
673                         }
674                         /* select */
675                         else {
676                                 for(a=me->totface; a>0; a--, tf++, mf++) {
677                                         if(!(tf->flag & TF_SELECT)) continue;
678                                         if(nearesttf && tf!=nearesttf)
679                                                 tf->flag &=~ TF_ACTIVE;
680                                         if (!sticky) continue;
681
682                                         if(msel_hit(limit, hitv, mf->v1, hituv, tf->uv[0]))
683                                                 tf->flag |= TF_SEL1;
684                                         if(msel_hit(limit, hitv, mf->v2, hituv, tf->uv[1]))
685                                                 tf->flag |= TF_SEL2;
686                                         if(msel_hit(limit, hitv, mf->v3, hituv, tf->uv[2]))
687                                                 tf->flag |= TF_SEL3;
688                                         if (mf->v4)
689                                                 if(msel_hit(limit, hitv, mf->v4, hituv, tf->uv[3]))
690                                                         tf->flag |= TF_SEL4;
691                                 }
692                         }
693                 }
694         }
695         else {
696                 /* select face and deselect other faces */ 
697                 if(actface) {
698                         mf= (MFace*)me->mface;
699                         tf= (TFace*)me->tface;
700                         for(a=me->totface; a>0; a--, tf++, mf++) {
701                                 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
702                                 if(nearesttf && tf!=nearesttf)
703                                         tf->flag &= ~TF_ACTIVE;
704                         }
705                         if(nearesttf)
706                                 nearesttf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
707                 }
708
709                 /* deselect uvs, and select sticky uvs */
710                 mf= (MFace*)me->mface;
711                 tf= (TFace*)me->tface;
712                 for(a=me->totface; a>0; a--, tf++, mf++) {
713                         if(tf->flag & TF_SELECT) {
714                                 if(!actface) tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
715                                 if(!sticky) continue;
716
717                                 if(msel_hit(limit, hitv, mf->v1, hituv, tf->uv[0]))
718                                         tf->flag |= TF_SEL1;
719                                 if(msel_hit(limit, hitv, mf->v2, hituv, tf->uv[1]))
720                                         tf->flag |= TF_SEL2;
721                                 if(msel_hit(limit, hitv, mf->v3, hituv, tf->uv[2]))
722                                         tf->flag |= TF_SEL3;
723                                 if(mf->v4)
724                                         if(msel_hit(limit, hitv, mf->v4, hituv, tf->uv[3]))
725                                                 tf->flag |= TF_SEL4;
726                         }
727                 }
728                 
729                 if(!actface) 
730                         nearesttf->flag |= TF_SEL_MASK(nearestuv);
731         }
732         
733         force_draw(1);
734         
735         BIF_undo_push("Select UV");
736         rightmouse_transform();
737 }
738
739 void borderselect_sima(short whichuvs)
740 {
741         Mesh *me;
742         TFace *tface;
743         MFace *mface;
744         rcti rect;
745         rctf rectf;
746         int a, val;
747         short mval[2];
748
749         if( is_uv_tface_editing_allowed()==0 ) return;
750         me= get_mesh(OBACT);
751
752         val= get_border(&rect, 3);
753
754         if(val) {
755                 mval[0]= rect.xmin;
756                 mval[1]= rect.ymin;
757                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
758                 mval[0]= rect.xmax;
759                 mval[1]= rect.ymax;
760                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
761
762                 mface= me->mface;
763                 for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) {
764                 
765                         if(tface->flag & TF_SELECT) {
766                                 
767                                 if (whichuvs == UV_SELECT_ALL) {
768                                 
769                                         if(BLI_in_rctf(&rectf, (float)tface->uv[0][0], (float)tface->uv[0][1])) {
770                                                 if(val==LEFTMOUSE) tface->flag |= TF_SEL1;
771                                                 else tface->flag &= ~TF_SEL1;
772                                         }
773                                         if(BLI_in_rctf(&rectf, (float)tface->uv[1][0], (float)tface->uv[1][1])) {
774                                                 if(val==LEFTMOUSE) tface->flag |= TF_SEL2;
775                                                 else tface->flag &= ~TF_SEL2;
776                                         }
777                                         if(BLI_in_rctf(&rectf, (float)tface->uv[2][0], (float)tface->uv[2][1])) {
778                                                 if(val==LEFTMOUSE) tface->flag |= TF_SEL3;
779                                                 else tface->flag &= ~TF_SEL3;
780                                         }
781                                         if(mface->v4 && BLI_in_rctf(&rectf, (float)tface->uv[3][0], (float)tface->uv[3][1])) {
782                                                 if(val==LEFTMOUSE) tface->flag |= TF_SEL4;
783                                                 else tface->flag &= ~TF_SEL4;
784                                         }
785                                 } else if (whichuvs == UV_SELECT_PINNED) {
786                                         if ((tface->unwrap & TF_PIN1) && 
787                                                 BLI_in_rctf(&rectf, (float)tface->uv[0][0], (float)tface->uv[0][1])) {
788                                                 
789                                                 if(val==LEFTMOUSE) tface->flag |= TF_SEL1;
790                                                 else tface->flag &= ~TF_SEL1;
791                                         }
792                                         if ((tface->unwrap & TF_PIN2) && 
793                                                 BLI_in_rctf(&rectf, (float)tface->uv[1][0], (float)tface->uv[1][1])) {
794                                                 
795                                                 if(val==LEFTMOUSE) tface->flag |= TF_SEL2;
796                                                 else tface->flag &= ~TF_SEL2;
797                                         }
798                                         if ((tface->unwrap & TF_PIN3) && 
799                                                 BLI_in_rctf(&rectf, (float)tface->uv[2][0], (float)tface->uv[2][1])) {
800                                                 
801                                                 if(val==LEFTMOUSE) tface->flag |= TF_SEL3;
802                                                 else tface->flag &= ~TF_SEL3;
803                                         }
804                                         if ((mface->v4) && (tface->unwrap & TF_PIN4) && BLI_in_rctf(&rectf, (float)tface->uv[3][0], (float)tface->uv[3][1])) {
805                                                 if(val==LEFTMOUSE) tface->flag |= TF_SEL4;
806                                                 else tface->flag &= ~TF_SEL4;
807                                         }
808                                 }
809                         }
810                                                         
811                 }
812                 BIF_undo_push("Border select UV");
813                 scrarea_queue_winredraw(curarea);
814         }
815 }
816
817 /** This is an ugly function to set the Tface selection flags depending
818   * on whether its UV coordinates are inside the normalized 
819   * area with radius rad and offset offset. These coordinates must be
820   * normalized to 1.0 
821   * Just for readability...
822   */
823
824 void sel_uvco_inside_radius(short sel, TFace *tface, int index, float *offset, float *ell, short select_mask)
825 {
826         // normalized ellipse: ell[0] = scaleX,
827         //                        [1] = scaleY
828
829         float *uv = tface->uv[index];
830         float x, y, r2;
831
832         x = (uv[0] - offset[0]) * ell[0];
833         y = (uv[1] - offset[1]) * ell[1];
834
835         r2 = x * x + y * y;
836         if (r2 < 1.0) {
837                 if (sel == LEFTMOUSE) tface->flag |= select_mask;
838                 else tface->flag &= ~select_mask;
839         }
840 }
841
842 // see below:
843 /** gets image dimensions of the 2D view 'v' */
844 static void getSpaceImageDimension(SpaceImage *sima, float *xy)
845 {
846         Image *img = sima->image;
847         float z;
848
849         z = sima->zoom;
850
851         if (img && img->ibuf) {
852                 xy[0] = img->ibuf->x * z;
853                 xy[1] = img->ibuf->y * z;
854         } else {
855                 xy[0] = 256 * z;
856                 xy[1] = 256 * z;
857         }
858 }
859
860 /** Callback function called by circle_selectCB to enable 
861   * brush select in UV editor.
862   */
863
864 void uvedit_selectionCB(short selecting, Object *editobj, short *mval, float rad) 
865 {
866         float offset[2];
867         Mesh *me;
868         MFace *mface;
869         TFace *tface;
870         int i;
871
872         float ellipse[2]; // we need to deal with ellipses, as
873                           // non square textures require for circle
874                                           // selection. this ellipse is normalized; r = 1.0
875         
876         me = get_mesh(editobj);
877
878         getSpaceImageDimension(curarea->spacedata.first, ellipse);
879         ellipse[0] /= rad;
880         ellipse[1] /= rad;
881
882         areamouseco_to_ipoco(G.v2d, mval, &offset[0], &offset[1]);
883
884         mface= me->mface;
885         tface= me->tface;
886
887         if (selecting) {
888                 for(i = 0; i < me->totface; i++) {
889                         sel_uvco_inside_radius(selecting, tface, 0, offset, ellipse, TF_SEL1);
890                         sel_uvco_inside_radius(selecting, tface, 1, offset, ellipse, TF_SEL2);
891                         sel_uvco_inside_radius(selecting, tface, 2, offset, ellipse, TF_SEL3);
892                         if (mface->v4)
893                                 sel_uvco_inside_radius(selecting, tface, 3, offset, ellipse, TF_SEL4);
894                         
895                         tface++; mface++;
896
897                 }
898
899                 if(G.f & G_DRAWFACES) { /* full redraw only if necessary */
900                         draw_sel_circle(0, 0, 0, 0, 0); /* signal */
901                         force_draw(0);
902                 }
903                 else { /* force_draw() is no good here... */
904                         glDrawBuffer(GL_FRONT);
905                         draw_tfaces();
906                         glDrawBuffer(GL_BACK);
907                 }
908         }       
909 }
910
911
912 void mouseco_to_curtile(void)
913 {
914         float fx, fy;
915         short mval[2];
916         
917         if( is_uv_tface_editing_allowed()==0) return;
918
919         if(G.sima->image && G.sima->image->tpageflag & IMA_TILES) {
920                 
921                 G.sima->flag |= SI_EDITTILE;
922                 
923                 while(get_mbut()&L_MOUSE) {
924                         
925                         calc_image_view(G.sima, 'f');
926                         
927                         getmouseco_areawin(mval);
928                         areamouseco_to_ipoco(G.v2d, mval, &fx, &fy);
929
930                         if(fx>=0.0 && fy>=0.0 && fx<1.0 && fy<1.0) {
931                         
932                                 fx= (fx)*G.sima->image->xrep;
933                                 fy= (fy)*G.sima->image->yrep;
934                                 
935                                 mval[0]= fx;
936                                 mval[1]= fy;
937                                 
938                                 G.sima->curtile= mval[1]*G.sima->image->xrep + mval[0];
939                         }
940
941                         scrarea_do_windraw(curarea);
942                         screen_swapbuffers();
943                 }
944                 
945                 G.sima->flag &= ~SI_EDITTILE;
946
947                 image_changed(G.sima, 1);
948
949                 allqueue(REDRAWVIEW3D, 0);
950                 scrarea_queue_winredraw(curarea);
951         }
952 }
953
954 void hide_tface_uv(int swap)
955 {
956         Mesh *me;
957         TFace *tface;
958         MFace *mface;
959         int a;
960
961         if( is_uv_tface_editing_allowed()==0 ) return;
962         me= get_mesh(OBACT);
963
964         if(swap) {
965                 mface= me->mface;
966                 for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) {
967                         if(tface->flag & TF_SELECT) {
968                                 if((tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3))==0) {
969                                         if(!mface->v4)
970                                                 tface->flag &= ~TF_SELECT;
971                                         else if(!(tface->flag & TF_SEL4))
972                                                 tface->flag &= ~TF_SELECT;
973                                 }
974                         }
975                 }
976         } else {
977                 mface= me->mface;
978                 for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) {
979                         if(tface->flag & TF_SELECT) {
980                                 if(tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
981                                                 tface->flag &= ~TF_SELECT;
982                                 else if(mface->v4 && tface->flag & TF_SEL4)
983                                                 tface->flag &= ~TF_SELECT;
984                         }
985                 }
986         }
987
988         BIF_undo_push("Hide UV");
989
990         object_tface_flags_changed(OBACT, 0);
991 }
992
993 void reveal_tface_uv(void)
994 {
995         Mesh *me;
996         TFace *tface;
997         MFace *mface;
998         int a;
999
1000         if( is_uv_tface_editing_allowed()==0 ) return;
1001         me= get_mesh(OBACT);
1002
1003         mface= me->mface;
1004         for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++)
1005                 if(!(tface->flag & TF_HIDE))
1006                         if(!(tface->flag & TF_SELECT))
1007                                 tface->flag |= (TF_SELECT|TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1008         
1009         BIF_undo_push("Reveal UV");
1010
1011         object_tface_flags_changed(OBACT, 0);
1012 }
1013
1014 void stitch_uv_tface(int mode)
1015 {
1016         Mesh *me;
1017         TFace *tf;
1018         int a, vtot;
1019         float newuv[2], limit[2];
1020         UvMapVert *vlist, *iterv, *v;
1021         UvVertMap *vmap;
1022         
1023         if(is_uv_tface_editing_allowed()==0)
1024                 return;
1025
1026         limit[0]= limit[1]= 20.0;
1027         if(mode==1) {
1028                 add_numbut(0, NUM|FLO, "Limit:", 0.1, 1000.0, &limit[0], NULL);
1029                 if (!do_clever_numbuts("Stitch UVs", 1, REDRAW))
1030                         return;
1031         }
1032
1033         if(G.sima->image && G.sima->image->ibuf && G.sima->image->ibuf->x > 0 &&
1034            G.sima->image->ibuf->y > 0) {
1035                 limit[1]= limit[0]/(float)G.sima->image->ibuf->y;
1036                 limit[0]= limit[0]/(float)G.sima->image->ibuf->x;
1037         }
1038         else
1039                 limit[0]= limit[1]= limit[0]/256.0;
1040
1041         me= get_mesh(OBACT);
1042         tf= me->tface;
1043
1044         vmap= make_uv_vert_map(me->mface, tf, me->totface, me->totvert, 1, limit);
1045         if(vmap == NULL)
1046                 return;
1047
1048         if(mode==0) {
1049                 for(a=0; a<me->totvert; a++) {
1050                         v = get_uv_map_vert(vmap, a);
1051
1052                         if(v == NULL)
1053                                 continue;
1054
1055                         newuv[0]= 0; newuv[1]= 0;
1056                         vtot= 0;
1057
1058                         for(iterv=v; iterv; iterv=iterv->next) {
1059                                 if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
1060                                         newuv[0] += tf[iterv->f].uv[iterv->tfindex][0];
1061                                         newuv[1] += tf[iterv->f].uv[iterv->tfindex][1];
1062                                         vtot++;
1063                                 }
1064                         }
1065
1066                         if (vtot > 1) {
1067                                 newuv[0] /= vtot; newuv[1] /= vtot;
1068
1069                                 for(iterv=v; iterv; iterv=iterv->next) {
1070                                         if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
1071                                                 tf[iterv->f].uv[iterv->tfindex][0]= newuv[0];
1072                                                 tf[iterv->f].uv[iterv->tfindex][1]= newuv[1];
1073                                         }
1074                                 }
1075                         }
1076                 }
1077         } else if(mode==1) {
1078                 for(a=0; a<me->totvert; a++) {
1079                         vlist= get_uv_map_vert(vmap, a);
1080
1081                         while(vlist) {
1082                                 newuv[0]= 0; newuv[1]= 0;
1083                                 vtot= 0;
1084
1085                                 for(iterv=vlist; iterv; iterv=iterv->next) {
1086                                         if((iterv != vlist) && iterv->separate)
1087                                                 break;
1088                                         if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
1089                                                 newuv[0] += tf[iterv->f].uv[iterv->tfindex][0];
1090                                                 newuv[1] += tf[iterv->f].uv[iterv->tfindex][1];
1091                                                 vtot++;
1092                                         }
1093                                 }
1094
1095                                 if (vtot > 1) {
1096                                         newuv[0] /= vtot; newuv[1] /= vtot;
1097
1098                                         for(iterv=vlist; iterv; iterv=iterv->next) {
1099                                                 if((iterv != vlist) && iterv->separate)
1100                                                         break;
1101                                                 if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
1102                                                         tf[iterv->f].uv[iterv->tfindex][0]= newuv[0];
1103                                                         tf[iterv->f].uv[iterv->tfindex][1]= newuv[1];
1104                                                 }
1105                                         }
1106                                 }
1107
1108                                 vlist= iterv;
1109                         }
1110                 }
1111         }
1112
1113         free_uv_vert_map(vmap);
1114
1115         if(G.sima->flag & SI_BE_SQUARE) be_square_tface_uv(me);
1116
1117         BIF_undo_push("Stitch UV");
1118
1119         object_uvs_changed(OBACT);
1120 }
1121
1122 void select_linked_tface_uv(int mode)
1123 {
1124         Mesh *me;
1125         MFace *mf;
1126         TFace *tf, *nearesttf=NULL;
1127         UvVertMap *vmap;
1128         UvMapVert *vlist, *iterv, *startv;
1129         unsigned int *stack, stacksize= 0, nearestv;
1130         char *flag;
1131         int a, nearestuv, i, nverts;
1132         float limit[2];
1133         
1134         if(is_uv_tface_editing_allowed()==0)
1135                 return;
1136
1137         me= get_mesh(OBACT);
1138
1139         if (mode == 2) {
1140                 nearesttf= NULL;
1141                 nearestuv= 0;
1142         }
1143         if (mode!=2) {
1144                 find_nearest_uv(&nearesttf, &nearestv, &nearestuv);
1145                 if(nearesttf==NULL)
1146                         return;
1147         }
1148
1149         get_connected_limit_tface_uv(limit);
1150         vmap= make_uv_vert_map(me->mface, me->tface, me->totface, me->totvert, 1, limit);
1151         if(vmap == NULL)
1152                 return;
1153
1154         stack= MEM_mallocN(sizeof(*stack)*me->totface, "UvLinkStack");
1155         flag= MEM_callocN(sizeof(*flag)*me->totface, "UvLinkFlag");
1156
1157         if (mode == 2) {
1158                 tf= me->tface;
1159                 for(a=0; a<me->totface; a++, tf++)
1160                         if(!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT))
1161                                 if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) {
1162                                         stack[stacksize]= a;
1163                                         stacksize++;
1164                                         flag[a]= 1;
1165                                 }
1166         }
1167         else {
1168                 tf= me->tface;
1169                 for(a=0; a<me->totface; a++, tf++)
1170                         if(tf == nearesttf) {
1171                                 stack[stacksize]= a;
1172                                 stacksize++;
1173                                 flag[a]= 1;
1174                                 break;
1175                         }
1176         }
1177
1178         while(stacksize > 0) {
1179                 stacksize--;
1180                 a= stack[stacksize];
1181                 mf= me->mface+a;
1182                 tf= me->tface+a;
1183
1184                 nverts= mf->v4? 4: 3;
1185
1186                 for(i=0; i<nverts; i++) {
1187                         vlist= get_uv_map_vert(vmap, *(&mf->v1 + i));
1188                         startv= vlist;
1189
1190                         for(iterv=vlist; iterv; iterv=iterv->next) {
1191                                 if(iterv->separate)
1192                                         startv= iterv;
1193                                 if(iterv->f == a)
1194                                         break;
1195                         }
1196
1197                         for(iterv=startv; iterv; iterv=iterv->next) {
1198                                 if((startv != iterv) && (iterv->separate))
1199                                         break;
1200                                 else if(!flag[iterv->f]) {
1201                                         flag[iterv->f]= 1;
1202                                         stack[stacksize]= iterv->f;;
1203                                         stacksize++;
1204                                 }
1205                         }
1206                 }
1207         }
1208
1209         if(mode==0 || mode==2) {
1210                 for(a=0, tf=me->tface; a<me->totface; a++, tf++)
1211                         if(flag[a])
1212                                 tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1213                         else
1214                                 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1215         }
1216         else if(mode==1) {
1217                 mf= me->mface;
1218                 for(a=0, tf=me->tface; a<me->totface; a++, tf++, mf++) {
1219                         if(flag[a]) {
1220                                 if (mf->v4) {
1221                                         if((tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)))
1222                                                 break;
1223                                 }
1224                                 else if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
1225                                         break;
1226                         }
1227                 }
1228
1229                 if (a<me->totface) {
1230                         for(a=0, tf=me->tface; a<me->totface; a++, tf++)
1231                                 if(flag[a])
1232                                         tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1233                 }
1234                 else {
1235                         for(a=0, tf=me->tface; a<me->totface; a++, tf++)
1236                                 if(flag[a])
1237                                         tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1238                 }
1239         }
1240         
1241         MEM_freeN(stack);
1242         MEM_freeN(flag);
1243         free_uv_vert_map(vmap);
1244
1245         BIF_undo_push("Select linked UV");
1246         scrarea_queue_winredraw(curarea);
1247 }
1248
1249 void unlink_selection(void)
1250 {
1251         Mesh *me;
1252         TFace *tface;
1253         MFace *mface;
1254         int a;
1255
1256         if( is_uv_tface_editing_allowed()==0 ) return;
1257         me= get_mesh(OBACT);
1258
1259         mface= me->mface;
1260         for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) {
1261                 if(tface->flag & TF_SELECT) {
1262                         if(mface->v4) {
1263                                 if(~tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4))
1264                                         tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1265                         } else {
1266                                 if(~tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
1267                                         tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3);
1268                         }
1269                 }
1270         }
1271         
1272         BIF_undo_push("Unlink UV selection");
1273         scrarea_queue_winredraw(curarea);
1274 }
1275
1276 void toggle_uv_select(int mode)
1277 {
1278         switch(mode){
1279         case 'f':
1280                 G.sima->flag ^= SI_SELACTFACE;
1281                 break;
1282         case 's':
1283                 G.sima->flag ^= SI_STICKYUVS; 
1284                 if (G.sima->flag & SI_STICKYUVS) G.sima->flag &= ~SI_LOCALSTICKY;
1285                 break;
1286         case 'l': 
1287                  G.sima->flag ^= SI_LOCALSTICKY;
1288                  if (G.sima->flag & SI_LOCALSTICKY) G.sima->flag &= ~SI_STICKYUVS;
1289                 break;
1290         case 'o':
1291                 G.sima->flag &= ~SI_STICKYUVS; 
1292                 G.sima->flag &= ~SI_LOCALSTICKY;
1293                 break;
1294         }
1295         allqueue(REDRAWIMAGE, 0);
1296 }
1297
1298 void pin_tface_uv(int mode)
1299 {
1300         Mesh *me;
1301         TFace *tface;
1302         MFace *mface;
1303         int a;
1304         
1305         if( is_uv_tface_editing_allowed()==0 ) return;
1306         me= get_mesh(OBACT);
1307         
1308         mface= me->mface;
1309         tface= me->tface;
1310         for(a=me->totface; a>0; a--, tface++, mface++) {
1311                 if(tface->flag & TF_SELECT) {
1312                         if(mode ==1){
1313                                 if(tface->flag & TF_SEL1) tface->unwrap |= TF_PIN1;
1314                                 if(tface->flag & TF_SEL2) tface->unwrap |= TF_PIN2;
1315                                 if(tface->flag & TF_SEL3) tface->unwrap |= TF_PIN3;
1316                                 if(mface->v4)
1317                                         if(tface->flag & TF_SEL4) tface->unwrap |= TF_PIN4;
1318                         }
1319                         else if (mode ==0){
1320                                 if(tface->flag & TF_SEL1) tface->unwrap &= ~TF_PIN1;
1321                                 if(tface->flag & TF_SEL2) tface->unwrap &= ~TF_PIN2;
1322                                 if(tface->flag & TF_SEL3) tface->unwrap &= ~TF_PIN3;
1323                                 if(mface->v4)
1324                                 if(tface->flag & TF_SEL4) tface->unwrap &= ~TF_PIN4;
1325                         }
1326                 }
1327         }
1328         
1329         BIF_undo_push("Pin UV");
1330         scrarea_queue_winredraw(curarea);
1331 }
1332
1333 void select_pinned_tface_uv(void)
1334 {
1335         Mesh *me;
1336         TFace *tface;
1337         MFace *mface;
1338         int a;
1339         
1340         if( is_uv_tface_editing_allowed()==0 ) return;
1341         me= get_mesh(OBACT);
1342         
1343         mface= me->mface;
1344         tface= me->tface;
1345         for(a=me->totface; a>0; a--, tface++, mface++) {
1346                 if(tface->flag & TF_SELECT) {
1347                 
1348                         if (tface->unwrap & TF_PIN1) tface->flag |= TF_SEL1;
1349                         if (tface->unwrap & TF_PIN2) tface->flag |= TF_SEL2;
1350                         if (tface->unwrap & TF_PIN3) tface->flag |= TF_SEL3;
1351                         if(mface->v4) {
1352                                 if (tface->unwrap & TF_PIN4) tface->flag |= TF_SEL4;
1353                         }
1354                         
1355                 }
1356         }
1357         
1358         BIF_undo_push("Select Pinned UVs");
1359         scrarea_queue_winredraw(curarea);
1360 }
1361
1362 int minmax_tface_uv(float *min, float *max)
1363 {
1364         Mesh *me;
1365         TFace *tf;
1366         MFace *mf;
1367         int a, sel;
1368
1369         if( is_uv_tface_editing_allowed()==0 ) return 0;
1370         me= get_mesh(OBACT);
1371
1372         INIT_MINMAX2(min, max);
1373
1374         sel= 0;
1375         mf= (MFace*)me->mface;
1376         tf= (TFace*)me->tface;
1377         for(a=me->totface; a>0; a--, tf++, mf++) {
1378                 if(tf->flag & TF_HIDE);
1379                 else if(tf->flag & TF_SELECT) {
1380
1381                         if (tf->flag & TF_SEL1) {
1382                                 DO_MINMAX2(tf->uv[0], min, max);
1383                         }
1384                         if (tf->flag & TF_SEL2) {
1385                                 DO_MINMAX2(tf->uv[1], min, max);
1386                         }
1387                         if (tf->flag & TF_SEL3) {
1388                                 DO_MINMAX2(tf->uv[2], min, max);
1389                         }
1390                         if (mf->v4 && tf->flag & TF_SEL4) {
1391                                 DO_MINMAX2(tf->uv[3], min, max);
1392                         }
1393
1394                         sel = 1;
1395                 }
1396         }
1397
1398         return sel;
1399 }
1400
1401 static void sima_show_info(int x, int y, char *cp, float *fp, int *zp, float *zpf)
1402 {
1403         short ofs;
1404         char str[256];
1405         
1406         ofs= sprintf(str, "X: %d Y: %d ", x, y);
1407         if(cp)
1408                 ofs+= sprintf(str+ofs, "| R: %d G: %d B: %d A: %d ", cp[0], cp[1], cp[2], cp[3]);
1409         if(fp)
1410                 ofs+= sprintf(str+ofs, "| R: %.3f G: %.3f B: %.3f A: %.3f ", fp[0], fp[1], fp[2], fp[3]);
1411         if(zp)
1412                 ofs+= sprintf(str+ofs, "| Z: %.4f ", 0.5+0.5*( ((float)*zp)/(float)0x7fffffff));
1413         if(zpf)
1414                 ofs+= sprintf(str+ofs, "| Z: %.3f ", *zpf);
1415         
1416         glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
1417         glEnable(GL_BLEND);
1418         
1419         glColor4f(.0,.0,.0,.25);
1420         glRectf(0.0, 0.0, curarea->winx, 30.0);
1421         glDisable(GL_BLEND);
1422         
1423         glColor3ub(255, 255, 255);
1424         glRasterPos2i(10, 10);
1425         
1426         BMF_DrawString(G.fonts, str);
1427
1428 }
1429
1430 void sima_sample_color(void)
1431 {
1432         ImBuf *ibuf;
1433         float fx, fy;
1434         short mval[2], mvalo[2], firsttime=1;
1435         
1436         if(G.sima->image==NULL) return;
1437         if(G.sima->image->ibuf==NULL) return;
1438         ibuf= G.sima->image->ibuf;
1439         
1440         calc_image_view(G.sima, 'f');
1441         getmouseco_areawin(mvalo);
1442         
1443         while(get_mbut() & L_MOUSE) {
1444                 
1445                 getmouseco_areawin(mval);
1446                 if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || firsttime) {
1447                         firsttime= 0;
1448                         areamouseco_to_ipoco(G.v2d, mval, &fx, &fy);
1449                         
1450                         if(fx>=0.0 && fy>=0.0 && fx<1.0 && fy<1.0) {
1451                                 float *fp= NULL, *zpf= NULL;
1452                                 int *zp= NULL;
1453                                 char *cp= NULL;
1454                                 
1455                                 int x= (int) (fx*ibuf->x);
1456                                 int y= (int) (fy*ibuf->y);
1457                                 
1458                                 if(x>=ibuf->x) x= ibuf->x-1;
1459                                 if(y>=ibuf->y) y= ibuf->y-1;
1460                                 
1461                                 if(ibuf->rect)
1462                                         cp= (char *)(ibuf->rect + y*ibuf->x + x);
1463                                 if(ibuf->zbuf)
1464                                         zp= ibuf->zbuf + y*ibuf->x + x;
1465                                 if(ibuf->zbuf_float)
1466                                         zpf= ibuf->zbuf_float + y*ibuf->x + x;
1467                                 if(ibuf->rect_float)
1468                                         fp= (ibuf->rect_float + 4*(y*ibuf->x + x));
1469                                         
1470                                 if(G.sima->cumap) {
1471                                         float vec[3];
1472                                         if(fp==NULL) {
1473                                                 fp= vec;
1474                                                 vec[0]= (float)cp[0]/255.0f;
1475                                                 vec[1]= (float)cp[1]/255.0f;
1476                                                 vec[2]= (float)cp[2]/255.0f;
1477                                         }
1478                                         
1479                                         if(G.qual & LR_CTRLKEY) {
1480                                                 curvemapping_set_black_white(G.sima->cumap, NULL, fp);
1481                                                 curvemapping_do_image(G.sima->cumap, G.sima->image);
1482                                         }
1483                                         else if(G.qual & LR_SHIFTKEY) {
1484                                                 curvemapping_set_black_white(G.sima->cumap, fp, NULL);
1485                                                 curvemapping_do_image(G.sima->cumap, G.sima->image);
1486                                         }
1487                                 }
1488                                 
1489                                 scrarea_do_windraw(curarea);
1490                                 myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
1491                                 glLoadIdentity();
1492                                 sima_show_info(x, y, cp, fp, zp, zpf);
1493                                 screen_swapbuffers();
1494                         }
1495                         
1496                 }
1497                 BIF_wait_for_statechange();
1498         }
1499         
1500         scrarea_queue_winredraw(curarea);
1501 }
1502
1503