Initial revision
[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 <math.h>
35
36 #ifndef WIN32
37 #include <unistd.h>
38 #else
39 #include <io.h>
40 #include "BLI_winstuff.h"
41 #endif   
42 #include "MEM_guardedalloc.h"
43
44 #include "BLI_blenlib.h"
45 #include "BLI_arithb.h"
46 #include "BLI_editVert.h"
47
48 #include "IMB_imbuf_types.h"
49
50 #include "DNA_mesh_types.h"
51 #include "DNA_scene_types.h"
52 #include "DNA_screen_types.h"
53 #include "DNA_userdef_types.h"
54 #include "DNA_space_types.h"
55 #include "DNA_image_types.h"
56 #include "DNA_object_types.h" // only for uvedit_selectionCB() (struct Object)
57
58 #include "BKE_global.h"
59 #include "BKE_mesh.h"
60
61 #include "BIF_gl.h"
62 #include "BIF_interface.h"
63 #include "BIF_screen.h"
64 #include "BIF_drawimage.h"
65 #include "BIF_editview.h"
66 #include "BIF_space.h"
67 #include "BIF_editsima.h"
68 #include "BIF_toolbox.h"
69 #include "BIF_mywindow.h"
70
71 #include "BSE_drawipo.h"
72 #include "BSE_edit.h"
73 #include "BSE_trans_types.h"
74
75 #include "BDR_editobject.h"
76
77 #include "blendef.h"
78 #include "mydevice.h"
79 #include "interface.h"
80
81 static int is_uv_tface_editing_allowed(void)
82 {
83         Mesh *me;
84
85         if(G.obedit) {error("Unable to perform function in EditMode"); return 0;}
86         if(G.sima->mode!=SI_TEXTURE) return 0;
87         if(!(G.f & G_FACESELECT)) return 0;  
88         me= get_mesh(OBACT);
89         if(me==0 || me->tface==0) return 0;
90         
91         return 1;
92 }
93
94 void clever_numbuts_sima(void)
95 {
96         float ocent[2], cent[2]= {0.0, 0.0};
97         int imx, imy;
98         int i, nactive= 0;
99         Mesh *me;
100         
101         if( is_uv_tface_editing_allowed()==0 ) return;
102         me= get_mesh(OBACT);
103         
104         if (G.sima->image && G.sima->image->ibuf) {
105                 imx= G.sima->image->ibuf->x;
106                 imy= G.sima->image->ibuf->y;
107         } else
108                 imx= imy= 256;
109         
110         for (i=0; i<me->totface; i++) {
111                 MFace *mf= &((MFace*) me->mface)[i];
112                 TFace *tf= &((TFace*) me->tface)[i];
113                 
114                 if (!mf->v3 || !(tf->flag & TF_SELECT))
115                         continue;
116                 
117                 if (tf->flag & TF_SEL1) {
118                         cent[0]+= tf->uv[0][0];
119                         cent[1]+= tf->uv[0][1];
120                         nactive++;
121                 }
122                 if (tf->flag & TF_SEL2) {
123                         cent[0]+= tf->uv[1][0];
124                         cent[1]+= tf->uv[1][1];
125                         nactive++;
126                 }
127                 if (tf->flag & TF_SEL3) {
128                         cent[0]+= tf->uv[2][0];
129                         cent[1]+= tf->uv[2][1];
130                         nactive++;
131                 }
132                 if (mf->v4 && (tf->flag & TF_SEL4)) {
133                         cent[0]+= tf->uv[3][0];
134                         cent[1]+= tf->uv[3][1];
135                         nactive++;
136                 }
137         }
138         
139         if (nactive) {
140                 cent[0]= (cent[0]*imx)/nactive;
141                 cent[1]= (cent[1]*imy)/nactive;
142
143                 add_numbut(0, NUM|FLO, "LocX:", -imx*20, imx*20, &cent[0], NULL);
144                 add_numbut(1, NUM|FLO, "LocY:", -imy*20, imy*20, &cent[1], NULL);
145                 
146                 ocent[0]= cent[0];
147                 ocent[1]= cent[1];
148                 if (do_clever_numbuts((nactive==1)?"Active Vertex":"Selected Center", 2, REDRAW)) {
149                         float delta[2];
150                         
151                         delta[0]= (cent[0]-ocent[0])/imx;
152                         delta[1]= (cent[1]-ocent[1])/imy;
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                                         tf->uv[0][0]+= delta[0];
163                                         tf->uv[0][1]+= delta[1];
164                                 }
165                                 if (tf->flag & TF_SEL2) {
166                                         tf->uv[1][0]+= delta[0];
167                                         tf->uv[1][1]+= delta[1];
168                                 }
169                                 if (tf->flag & TF_SEL3) {
170                                         tf->uv[2][0]+= delta[0];
171                                         tf->uv[2][1]+= delta[1];
172                                 }
173                                 if (mf->v4 && (tf->flag & TF_SEL4)) {
174                                         tf->uv[3][0]+= delta[0];
175                                         tf->uv[3][1]+= delta[1];
176                                 }
177                         }
178                         
179                         allqueue(REDRAWVIEW3D, 0);
180                 }
181         }
182 }
183
184 static void sima_pixelgrid(float *loc, float sx, float sy)
185 {
186         float y;
187         float x;
188         
189         if(G.sima->image && G.sima->image->ibuf) {
190                 x= G.sima->image->ibuf->x;
191                 y= G.sima->image->ibuf->y;
192         
193                 sx= floor(x*sx)/x;
194                 if(G.sima->flag & SI_CLIP_UV) {
195                         CLAMP(sx, 0, 1.0);
196                 }
197                 loc[0]= sx;
198                 
199                 sy= floor(y*sy)/y;
200                 if(G.sima->flag & SI_CLIP_UV) {
201                         CLAMP(sy, 0, 1.0);
202                 }
203                 loc[1]= sy;
204         }
205         else {
206                 loc[0]= sx;
207                 loc[1]= sy;
208         }
209 }
210
211
212 static void be_square_tface_uv(Mesh *me)
213 {
214         TFace *tface;
215         MFace *mface;
216         int a;
217         
218         /* als 1 punt select: doit (met het select punt) */
219         for(a=me->totface, mface= me->mface, tface= me->tface; a>0; a--, tface++, mface++) {
220                 if(mface->v4) {
221                         if(tface->flag & TF_SELECT) {
222                                 if(tface->flag & TF_SEL1) {
223                                         if( tface->uv[1][0] == tface->uv[2][0] ) {
224                                                 tface->uv[1][1]= tface->uv[0][1];
225                                                 tface->uv[3][0]= tface->uv[0][0];
226                                         }
227                                         else {  
228                                                 tface->uv[1][0]= tface->uv[0][0];
229                                                 tface->uv[3][1]= tface->uv[0][1];
230                                         }
231                                         
232                                 }
233                                 if(tface->flag & TF_SEL2) {
234                                         if( tface->uv[2][1] == tface->uv[3][1] ) {
235                                                 tface->uv[2][0]= tface->uv[1][0];
236                                                 tface->uv[0][1]= tface->uv[1][1];
237                                         }
238                                         else {
239                                                 tface->uv[2][1]= tface->uv[1][1];
240                                                 tface->uv[0][0]= tface->uv[1][0];
241                                         }
242
243                                 }
244                                 if(tface->flag & TF_SEL3) {
245                                         if( tface->uv[3][0] == tface->uv[0][0] ) {
246                                                 tface->uv[3][1]= tface->uv[2][1];
247                                                 tface->uv[1][0]= tface->uv[2][0];
248                                         }
249                                         else {
250                                                 tface->uv[3][0]= tface->uv[2][0];
251                                                 tface->uv[1][1]= tface->uv[2][1];
252                                         }
253                                 }
254                                 if(tface->flag & TF_SEL4) {
255                                         if( tface->uv[0][1] == tface->uv[1][1] ) {
256                                                 tface->uv[0][0]= tface->uv[3][0];
257                                                 tface->uv[2][1]= tface->uv[3][1];
258                                         }
259                                         else  {
260                                                 tface->uv[0][1]= tface->uv[3][1];
261                                                 tface->uv[2][0]= tface->uv[3][0];
262                                         }
263
264                                 }
265                         }
266                 }
267         }
268
269 }
270
271 void tface_do_clip(void)
272 {
273         Mesh *me;
274         TFace *tface;
275         int a, b;
276         
277         if( is_uv_tface_editing_allowed()==0 ) return;
278         me= get_mesh(OBACT);
279         tface= me->tface;
280         
281         for(a=0; a<me->totface; a++, tface++) {
282                 if(tface->flag & TF_SELECT) {
283                         for(b=0; b<4; b++) {
284                                 CLAMP(tface->uv[b][0], 0.0, 1.0);
285                                 CLAMP(tface->uv[b][1], 0.0, 1.0);
286                         }
287                 }
288         }
289         
290 }
291
292 void transform_tface_uv(int mode)
293 {
294         MFace *mface;
295         TFace *tface;
296         Mesh *me;
297         TransVert *transmain, *tv;
298         float asp, dx1, dx2, dy1, dy2, phi, dphi, co, si;
299         float xref=1.0, yref=1.0, size[2], sizefac;
300         float dx, dy, dvec2[2], dvec[2], div, cent[2];
301         float x, y, min[2], max[2], vec[2], xtra[2], ivec[2];
302         int xim, yim, tot=0, a, b, firsttime=1, afbreek=0, midtog= 0, proj = 0;
303         unsigned short event = 0;
304         short mval[2], val, xo, yo, xn, yn, xc, yc;
305         char str[32];
306         
307         if( is_uv_tface_editing_allowed()==0 ) return;
308         me= get_mesh(OBACT);
309         
310         min[0]= min[1]= 10000.0;
311         max[0]= max[1]= -10000.0;
312         
313         calc_image_view(G.sima, 'f');
314         
315         if(G.sima->image && G.sima->image->ibuf) {
316                 xim= G.sima->image->ibuf->x;
317                 yim= G.sima->image->ibuf->y;
318         }
319         else {
320                 xim= yim= 256;
321         }
322         /* welke vertices doen mee */
323         
324         for(a=me->totface, tface= me->tface, mface= me->mface; a>0; a--, tface++, mface++) {
325                 if((tface->flag & TF_SELECT) && mface->v3) {
326                         if(tface->flag & TF_SEL1) tot++;
327                         if(tface->flag & TF_SEL2) tot++;
328                         if(tface->flag & TF_SEL3) tot++;
329                         if(tface->flag & TF_SEL4) tot++; 
330                 }
331         }
332         if(tot==0) return;
333         
334         tv=transmain= MEM_callocN(tot*sizeof(TransVert), "transmain");
335
336         for(a=me->totface, tface= me->tface, mface= me->mface; a>0; a--, tface++, mface++) {
337                 if((tface->flag & TF_SELECT) && mface->v3) {
338                         if(tface->flag & TF_SEL1) {
339                                 tv->loc= tface->uv[0];
340                                 tv++;
341                         }
342                         if(tface->flag & TF_SEL2) {
343                                 tv->loc= tface->uv[1];
344                                 tv++;
345                         }
346                         if(tface->flag & TF_SEL3) {
347                                 tv->loc= tface->uv[2];
348                                 tv++;
349                         }
350                         if(tface->flag & TF_SEL4) {
351                                 tv->loc= tface->uv[3];
352                                 tv++;
353                         }
354                 }
355         }
356         
357         a= tot;
358         tv= transmain;
359         while(a--) {
360                 tv->oldloc[0]= tv->loc[0];
361                 tv->oldloc[1]= tv->loc[1];
362                 DO_MINMAX2(tv->loc, min, max);
363                 tv++;
364         }
365         
366         cent[0]= (min[0]+max[0])/2.0;
367         cent[1]= (min[1]+max[1])/2.0;
368
369         ipoco_to_areaco_noclip(G.v2d, cent, mval);
370         xc= mval[0];
371         yc= mval[1];
372         
373         getmouseco_areawin(mval);
374         xo= xn= mval[0];
375         yo= yn= mval[1];
376         dvec[0]= dvec[1]= 0.0;
377         dx1= xc-xn; 
378         dy1= yc-yn;
379         phi= 0.0;
380         
381         
382         sizefac= sqrt( (float)((yc-yn)*(yc-yn)+(xn-xc)*(xn-xc)) );
383         if(sizefac<2.0) sizefac= 2.0;
384
385         while(afbreek==0) {
386                 getmouseco_areawin(mval);
387                 if(mval[0]!=xo || mval[1]!=yo || firsttime) {
388                         
389                         if(mode=='g') {
390                         
391                                 dx= mval[0]- xo;
392                                 dy= mval[1]- yo;
393         
394                                 div= G.v2d->mask.xmax-G.v2d->mask.xmin;
395                                 dvec[0]+= (G.v2d->cur.xmax-G.v2d->cur.xmin)*(dx)/div;
396         
397                                 div= G.v2d->mask.ymax-G.v2d->mask.ymin;
398                                 dvec[1]+= (G.v2d->cur.ymax-G.v2d->cur.ymin)*(dy)/div;
399                                 
400                                 if(midtog) dvec[proj]= 0.0;
401                                 
402                                 dvec2[0]= dvec[0];
403                                 dvec2[1]= dvec[1];
404                                 apply_keyb_grid(dvec2, 0.0, 1.0/8.0, 1.0/16.0, U.flag & AUTOGRABGRID);
405                                 apply_keyb_grid(dvec2+1, 0.0, 1.0/8.0, 1.0/16.0, U.flag & AUTOGRABGRID);
406
407                                 vec[0]= dvec2[0];
408                                 vec[1]= dvec2[1];
409                                 
410                                 if(G.sima->flag & SI_CLIP_UV) {
411                                         if(vec[0]< -min[0]) vec[0]= -min[0];
412                                         if(vec[1]< -min[1]) vec[1]= -min[1];
413                                         if(vec[0]> 1.0-max[0]) vec[0]= 1.0-max[0];
414                                         if(vec[1]> 1.0-max[1]) vec[1]= 1.0-max[1];
415                                 }
416                                 tv= transmain;
417                                 for(a=0; a<tot; a++, tv++) {
418                                         
419                                         x= tv->oldloc[0]+vec[0];
420                                         y= tv->oldloc[1]+vec[1];
421                                                 
422                                         sima_pixelgrid(tv->loc, x, y);
423                                 }
424                                 ivec[0]= (vec[0]*xim);
425                                 ivec[1]= (vec[1]*yim);
426
427                                 if(G.sima->flag & SI_BE_SQUARE) be_square_tface_uv(me);
428                         
429                                 sprintf(str, "X: %.4f   Y: %.4f  ", ivec[0], ivec[1]);
430                                 headerprint(str);
431                         }
432                         else if(mode=='r') {
433
434                                 dx2= xc-mval[0];
435                                 dy2= yc-mval[1];
436                                 
437                                 div= sqrt( (dx1*dx1+dy1*dy1)*(dx2*dx2+dy2*dy2));
438                                 if(div>1.0) {
439                                 
440                                         dphi= (dx1*dx2+dy1*dy2)/div;
441                                         dphi= saacos(dphi);
442                                         if( (dx1*dy2-dx2*dy1)<0.0 ) dphi= -dphi;
443                                         
444                                         if(G.qual & LR_SHIFTKEY) phi+= dphi/30.0;
445                                         else phi+= dphi;
446                                         
447                                         apply_keyb_grid(&phi, 0.0, (5.0/180)*M_PI, (1.0/180)*M_PI, U.flag & AUTOROTGRID);
448                                         
449                                         dx1= dx2; 
450                                         dy1= dy2;
451                                         
452                                         co= cos(phi);
453                                         si= sin(phi);
454                                         asp= (float)yim/(float)xim;
455
456                                         
457                                         tv= transmain;
458                                         for(a=0; a<tot; a++, tv++) {
459                                                 
460                                                 x= ( co*( tv->oldloc[0]-cent[0]) - si*asp*(tv->oldloc[1]-cent[1]) ) +cent[0];
461                                                 y= ( si*( tv->oldloc[0]-cent[0])/asp + co*(tv->oldloc[1]-cent[1]) ) +cent[1];
462                                                 sima_pixelgrid(tv->loc, x, y);
463                                                 
464                                                 if(G.sima->flag & SI_CLIP_UV) {
465                                                         if(tv->loc[0]<0.0) tv->loc[0]= 0.0;
466                                                         else if(tv->loc[0]>1.0) tv->loc[0]= 1.0;
467                                                         if(tv->loc[1]<0.0) tv->loc[1]= 0.0;
468                                                         else if(tv->loc[1]>1.0) tv->loc[1]= 1.0;
469                                                 }
470                                         }                                       
471                                         
472                                         
473                                         sprintf(str, "Rot: %.3f  ", phi*180.0/M_PI);
474                                         headerprint(str);
475                                 }
476                         }
477                         else if(mode=='s') {
478                                 
479                                 size[0]=size[1]= (sqrt( (float)((yc-mval[1])*(yc-mval[1])+(mval[0]-xc)*(mval[0]-xc)) ))/sizefac;
480                                 
481                                 if(midtog) size[proj]= 1.0;
482                                 
483                                 apply_keyb_grid(size, 0.0, 0.1, 0.01, U.flag & AUTOSIZEGRID);
484                                 apply_keyb_grid(size+1, 0.0, 0.1, 0.01, U.flag & AUTOSIZEGRID);
485
486                                 size[0]*= xref;
487                                 size[1]*= yref;
488                                 
489                                 xtra[0]= xtra[1]= 0;
490
491                                 if(G.sima->flag & SI_CLIP_UV) {
492                                         /* boundbox limit: four step plan: XTRA X */
493         
494                                         a=b= 0;
495                                         if(size[0]*(min[0]-cent[0]) + cent[0] + xtra[0] < 0) 
496                                                 a= -size[0]*(min[0]-cent[0]) - cent[0];
497                                         if(size[0]*(max[0]-cent[0]) + cent[0] + xtra[0] > 1.0) 
498                                                 b= 1.0 - size[0]*(max[0]-cent[0]) - cent[0];
499                                         xtra[0]= (a+b)/2;
500                                         
501                                         /* SIZE X */
502                                         if(size[0]*(min[0]-cent[0]) + cent[0] + xtra[0] < 0) 
503                                                 size[0]= (-cent[0]-xtra[0])/(min[0]-cent[0]);
504                                         if(size[0]*(max[0]-cent[0]) + cent[0] +xtra[0] > 1.0) 
505                                                 size[0]= (1.0-cent[0]-xtra[0])/(max[0]-cent[0]);
506                                                 
507                                         /* XTRA Y */
508                                         a=b= 0;
509                                         if(size[1]*(min[1]-cent[1]) + cent[1] + xtra[1] < 0) 
510                                                 a= -size[1]*(min[1]-cent[1]) - cent[1];
511                                         if(size[1]*(max[1]-cent[1]) + cent[1] + xtra[1] > 1.0) 
512                                                 b= 1.0 - size[1]*(max[1]-cent[1]) - cent[1];
513                                         xtra[1]= (a+b)/2;
514                                         
515                                         /* SIZE Y */
516                                         if(size[1]*(min[1]-cent[1]) + cent[1] +xtra[1] < 0) 
517                                                 size[1]= (-cent[1]-xtra[1])/(min[1]-cent[1]);
518                                         if(size[1]*(max[1]-cent[1]) + cent[1] + xtra[1]> 1.0) 
519                                                 size[1]= (1.0-cent[1]-xtra[1])/(max[1]-cent[1]);
520                                 }
521
522                                 /* if(midtog==0) { */
523                                 /*      if(size[1]>size[0]) size[1]= size[0]; */
524                                 /*      else if(size[0]>size[1]) size[0]= size[1]; */
525                                 /* } */
526
527                                 tv= transmain;
528                                 for(a=0; a<tot; a++, tv++) {
529                                         
530                                         x= size[0]*(tv->oldloc[0]-cent[0])+ cent[0] + xtra[0];
531                                         y= size[1]*(tv->oldloc[1]-cent[1])+ cent[1] + xtra[1];
532                                         sima_pixelgrid(tv->loc, x, y);
533                                 }
534                                 
535                                 sprintf(str, "sizeX: %.3f   sizeY: %.3f  ", size[0], size[1]);
536                                 headerprint(str);
537                                 
538                         }
539                         
540                         xo= mval[0];
541                         yo= mval[1];
542                         
543                         if(G.sima->lock) force_draw_plus(SPACE_VIEW3D);
544                         else force_draw();
545                         
546                         firsttime= 0;
547                         
548                 }
549                 else BIF_wait_for_statechange();
550                 
551                 while(qtest()) {
552                         event= extern_qread(&val);
553                         if(val) {
554                                 switch(event) {
555                                 case ESCKEY:
556                                 case RIGHTMOUSE:
557                                 case LEFTMOUSE:
558                                 case SPACEKEY:
559                                 case RETKEY:
560                                         afbreek= 1;
561                                         break;
562                                 case MIDDLEMOUSE:
563                                         
564                                         midtog= ~midtog;
565                                         if(midtog) {
566                                                 if( abs(mval[0]-xn) > abs(mval[1]-yn)) proj= 1;
567                                                 else proj= 0;
568                                                 firsttime= 1;
569                                         }
570                                 
571                                         break;
572                                 case XKEY:
573                                 case YKEY:
574                                         if(event==XKEY) xref= -xref;
575                                         else yref= -yref;
576                                         
577                                         firsttime= 1;
578                                         break;
579                                 default:
580                                         arrows_move_cursor(event);
581                                 }
582                         }
583                         if(afbreek) break;
584                 }
585         }
586         
587         if(event==ESCKEY || event == RIGHTMOUSE) {
588                 tv= transmain;
589                 for(a=0; a<tot; a++, tv++) {
590                         tv->loc[0]= tv->oldloc[0];
591                         tv->loc[1]= tv->oldloc[1];
592                 }
593         }
594         MEM_freeN(transmain);
595         
596         if(mode=='g') if(G.sima->flag & SI_BE_SQUARE) be_square_tface_uv(me);
597                         
598         allqueue(REDRAWVIEW3D, 0);
599         scrarea_queue_headredraw(curarea);
600         scrarea_queue_winredraw(curarea);
601 }
602
603 void select_swap_tface_uv(void)
604 {
605         Mesh *me;
606         TFace *tface;
607         MFace *mface;
608         int a, sel=0;
609         
610         if( is_uv_tface_editing_allowed()==0 ) return;
611         me= get_mesh(OBACT);
612
613         for(a=me->totface, tface= me->tface; a>0; a--, tface++) {
614                 if(tface->flag & TF_SELECT) {   
615                         if(tface->flag & (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4)) {
616                                 sel= 1;
617                                 break;
618                         }
619                 }
620         }
621         
622         mface= me->mface;
623         for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) {
624                 if(tface->flag & TF_SELECT) {
625                         if(mface->v4) {
626                                 if(sel) tface->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
627                                 else tface->flag |= (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
628                         }
629                         else if(mface->v3) {
630                                 if(sel) tface->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
631                                 else tface->flag |= (TF_SEL1+TF_SEL2+TF_SEL3);
632                         }
633                 }
634         }
635         
636         allqueue(REDRAWIMAGE, 0);
637 }
638
639 void mouse_select_sima(void)
640 {
641         Mesh *me;
642         TFace *tface;
643         MFace *mface;
644         int temp, dist=100;
645         int a;
646         short mval[2], uval[2], val = 0;
647         char *flagpoin =0;
648         
649         if( is_uv_tface_editing_allowed()==0 ) return;
650         me= get_mesh(OBACT);
651         
652         getmouseco_areawin(mval);       
653
654         mface= me->mface;
655         for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) {
656                 
657                 if(tface->flag & TF_SELECT) {
658                 
659                         uvco_to_areaco_noclip(tface->uv[0], uval);
660                         temp= abs(mval[0]- uval[0])+ abs(mval[1]- uval[1]);
661                         if( tface->flag & TF_SEL1) temp+=5;
662                         if(temp<dist) { 
663                                 flagpoin= &tface->flag;
664                                 dist= temp; 
665                                 val= TF_SEL1;
666                         }
667         
668                         uvco_to_areaco_noclip(tface->uv[1], uval);
669                         temp= abs(mval[0]- uval[0])+ abs(mval[1]- uval[1]);
670                         if( tface->flag & TF_SEL2) temp+=5;
671                         if(temp<dist) { 
672                                 flagpoin= &tface->flag;
673                                 dist= temp; 
674                                 val= TF_SEL2;
675                         }
676         
677                         uvco_to_areaco_noclip(tface->uv[2], uval);
678                         temp= abs(mval[0]- uval[0])+ abs(mval[1]- uval[1]);
679                         if( tface->flag & TF_SEL3) temp+=5;
680                         if(temp<dist) { 
681                                 flagpoin= &tface->flag;
682                                 dist= temp; 
683                                 val= TF_SEL3;
684                         }
685         
686                         if(mface->v4) {
687                                 uvco_to_areaco_noclip(tface->uv[3], uval);
688                                 temp= abs(mval[0]- uval[0])+ abs(mval[1]- uval[1]);
689                                 if( tface->flag & TF_SEL4) temp+=5;
690                                 if(temp<dist) { 
691                                         flagpoin= &tface->flag;
692                                         dist= temp; 
693                                         val= TF_SEL4;
694                                 }
695                         }
696                         
697                 }
698         }
699         
700         if(flagpoin) {
701                 if(G.qual & LR_SHIFTKEY) {
702                         if(*flagpoin & val) *flagpoin &= ~val;
703                         else *flagpoin |= val;
704                 }
705                 else {
706                         for(a=me->totface, tface= me->tface; a>0; a--, tface++) {
707                                 if(tface->flag & TF_SELECT) {
708                                         tface->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
709                                 }
710                         }
711                         
712                         *flagpoin |= val;
713                 }
714                 
715         
716                 glDrawBuffer(GL_FRONT);
717                 draw_tfaces();
718                 glDrawBuffer(GL_BACK);
719                 
720                 std_rmouse_transform(transform_tface_uv);
721         }
722 }
723
724 void borderselect_sima(void)
725 {
726         Mesh *me;
727         TFace *tface;
728         MFace *mface;
729         rcti rect;
730         rctf rectf;
731         int a, val;
732         short mval[2];
733
734         if( is_uv_tface_editing_allowed()==0 ) return;
735         me= get_mesh(OBACT);
736
737         val= get_border(&rect, 3);
738
739         if(val) {
740                 mval[0]= rect.xmin;
741                 mval[1]= rect.ymin;
742                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
743                 mval[0]= rect.xmax;
744                 mval[1]= rect.ymax;
745                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
746
747                 mface= me->mface;
748                 for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) {
749                 
750                         if(tface->flag & TF_SELECT) {
751                                 
752                                 if(BLI_in_rctf(&rectf, (float)tface->uv[0][0], (float)tface->uv[0][1])) {
753                                         if(val==LEFTMOUSE) tface->flag |= TF_SEL1;
754                                         else tface->flag &= ~TF_SEL1;
755                                 }
756                                 if(BLI_in_rctf(&rectf, (float)tface->uv[1][0], (float)tface->uv[1][1])) {
757                                         if(val==LEFTMOUSE) tface->flag |= TF_SEL2;
758                                         else tface->flag &= ~TF_SEL2;
759                                 }
760                                 if(BLI_in_rctf(&rectf, (float)tface->uv[2][0], (float)tface->uv[2][1])) {
761                                         if(val==LEFTMOUSE) tface->flag |= TF_SEL3;
762                                         else tface->flag &= ~TF_SEL3;
763                                 }
764                                 if(mface->v4 && BLI_in_rctf(&rectf, (float)tface->uv[3][0], (float)tface->uv[3][1])) {
765                                         if(val==LEFTMOUSE) tface->flag |= TF_SEL4;
766                                         else tface->flag &= ~TF_SEL4;
767                                 }
768                         }
769                                                         
770                 }
771                 scrarea_queue_winredraw(curarea);
772         }
773 }
774
775 /** This is an ugly function to set the Tface selection flags depending
776   * on whether its UV coordinates are inside the normalized 
777   * area with radius rad and offset offset. These coordinates must be
778   * normalized to 1.0 
779   * Just for readability...
780   */
781
782 void sel_uvco_inside_radius(short sel, TFace *tface, int index, float *offset, float *ell, short select_mask)
783 {
784         // normalized ellipse: ell[0] = scaleX,
785         //                        [1] = scaleY
786
787         float *uv = tface->uv[index];
788         float x, y, r2;
789
790         x = (uv[0] - offset[0]) * ell[0];
791         y = (uv[1] - offset[1]) * ell[1];
792
793         r2 = x * x + y * y;
794         if (r2 < 1.0) {
795                 if (sel == LEFTMOUSE) tface->flag |= select_mask;
796                 else tface->flag &= ~select_mask;
797         }
798 }
799
800 // see below:
801 /** gets image dimensions of the 2D view 'v' */
802 static void getSpaceImageDimension(SpaceImage *sima, float *xy)
803 {
804         Image *img = sima->image;
805         float z;
806
807         z = sima->zoom;
808
809         if (img) {
810                 xy[0] = img->ibuf->x * z;
811                 xy[1] = img->ibuf->y * z;
812         } else {
813                 xy[0] = 256 * z;
814                 xy[1] = 256 * z;
815         }
816 }
817
818 /** Callback function called by circle_selectCB to enable 
819   * brush select in UV editor.
820   */
821
822 void uvedit_selectionCB(short selecting, Object *editobj, short *mval, float rad) 
823 {
824         float offset[2];
825         Mesh *me;
826         MFace *mface;
827         TFace *tface;
828         int i;
829
830         float ellipse[2]; // we need to deal with ellipses, as
831                           // non square textures require for circle
832                                           // selection. this ellipse is normalized; r = 1.0
833         
834         me = get_mesh(editobj);
835
836         getSpaceImageDimension(curarea->spacedata.first, ellipse);
837         ellipse[0] /= rad;
838         ellipse[1] /= rad;
839
840         areamouseco_to_ipoco(G.v2d, mval, &offset[0], &offset[1]);
841
842         mface= me->mface;
843         tface= me->tface;
844
845         if (selecting) {
846                 for(i = 0; i < me->totface; i++) {
847                         sel_uvco_inside_radius(selecting, tface, 0, offset, ellipse, TF_SEL1);
848                         sel_uvco_inside_radius(selecting, tface, 1, offset, ellipse, TF_SEL2);
849                         sel_uvco_inside_radius(selecting, tface, 2, offset, ellipse, TF_SEL3);
850                         if (mface->v4)
851                                 sel_uvco_inside_radius(selecting, tface, 3, offset, ellipse, TF_SEL4);
852                         
853                         tface++; mface++;
854
855                 }
856         // force_draw() is no good here...
857                 glDrawBuffer(GL_FRONT);
858                 draw_tfaces();
859                 glDrawBuffer(GL_BACK);
860         }       
861 }
862
863
864 void mouseco_to_curtile(void)
865 {
866         float fx, fy;
867         short mval[2];
868         
869         if( is_uv_tface_editing_allowed()==0) return;
870
871         if(G.sima->image && G.sima->image->tpageflag & IMA_TILES) {
872                 
873                 G.sima->flag |= SI_EDITTILE;
874                 
875                 while(get_mbut()&L_MOUSE) {
876                         
877                         calc_image_view(G.sima, 'f');
878                         
879                         getmouseco_areawin(mval);
880                         areamouseco_to_ipoco(G.v2d, mval, &fx, &fy);
881
882                         if(fx>=0.0 && fy>=0.0 && fx<1.0 && fy<1.0) {
883                         
884                                 fx= (fx)*G.sima->image->xrep;
885                                 fy= (fy)*G.sima->image->yrep;
886                                 
887                                 mval[0]= fx;
888                                 mval[1]= fy;
889                                 
890                                 G.sima->curtile= mval[1]*G.sima->image->xrep + mval[0];
891                         }
892
893                         scrarea_do_windraw(curarea);
894                         screen_swapbuffers();
895                 
896                 }
897                 
898                 G.sima->flag &= ~SI_EDITTILE;
899
900                 image_changed(G.sima, 1);
901
902                 allqueue(REDRAWVIEW3D, 0);
903                 scrarea_queue_winredraw(curarea);
904         }
905 }