Changed frame numbering to only alter hashes if they are in the filename (not the...
[blender-staging.git] / source / blender / src / editsima.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL 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.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #ifndef WIN32
39 #include <unistd.h>
40 #else
41 #include <io.h>
42 #endif   
43 #include "MEM_guardedalloc.h"
44
45 #include "BLI_blenlib.h"
46 #include "BLI_arithb.h"
47 #include "BLI_editVert.h"
48
49 #include "IMB_imbuf_types.h"
50 #include "IMB_imbuf.h"
51
52 #include "DNA_image_types.h"
53 #include "DNA_mesh_types.h"
54 #include "DNA_meshdata_types.h"
55 #include "DNA_node_types.h"
56 #include "DNA_object_types.h" // only for uvedit_selectionCB() (struct Object)
57 #include "DNA_packedFile_types.h"
58 #include "DNA_scene_types.h"
59 #include "DNA_space_types.h"
60 #include "DNA_screen_types.h"
61 #include "DNA_texture_types.h"
62 #include "DNA_userdef_types.h"
63 #include "DNA_view3d_types.h"
64
65 #include "BKE_colortools.h"
66 #include "BKE_depsgraph.h"
67 #include "BKE_displist.h"
68 #include "BKE_image.h"
69 #include "BKE_global.h"
70 #include "BKE_library.h"
71 #include "BKE_main.h"
72 #include "BKE_mesh.h"
73 #include "BKE_node.h"
74 #include "BKE_object.h"
75 #include "BKE_packedFile.h"
76 #include "BKE_utildefines.h"
77
78 #include "BIF_gl.h"
79 #include "BIF_glutil.h"
80 #include "BIF_imasel.h"
81 #include "BIF_interface.h"
82 #include "BIF_drawimage.h"
83 #include "BIF_editview.h"
84 #include "BIF_editsima.h"
85 #include "BIF_mywindow.h"
86 #include "BIF_previewrender.h"
87 #include "BIF_screen.h"
88 #include "BIF_space.h"
89 #include "BIF_toolbox.h"
90 #include "BIF_transform.h"
91 #include "BIF_writeimage.h"
92 #include "BIF_editmesh.h"
93
94 #include "BSE_drawipo.h"
95 #include "BSE_edit.h"
96 #include "BSE_filesel.h"
97 #include "BSE_node.h"
98 #include "BSE_trans_types.h"
99
100 #include "BDR_editobject.h"
101 #include "BDR_unwrapper.h"
102
103 #include "BMF_Api.h"
104
105 #include "RE_pipeline.h"
106
107 #include "blendef.h"
108 #include "multires.h"
109 #include "mydevice.h"
110 #include "editmesh.h"
111
112 /* local prototypes */
113 void sel_uvco_inside_radius(short , EditFace *efa, MTFace *, int , float *, float *, short);
114 void uvedit_selectionCB(short , Object *, short *, float ); /* used in edit.c*/ 
115
116 void object_uvs_changed(Object *ob)
117 {
118         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
119
120         allqueue(REDRAWVIEW3D, 0);
121         allqueue(REDRAWIMAGE, 0);
122 }
123
124 void object_tface_flags_changed(Object *ob, int updateButtons)
125 {
126         if (updateButtons) allqueue(REDRAWBUTSEDIT, 0);
127         allqueue(REDRAWVIEW3D, 0);
128         allqueue(REDRAWIMAGE, 0);
129 }
130
131 int is_uv_tface_editing_allowed_silent(void)
132 {
133         if(!EM_texFaceCheck()) return 0;
134         if(G.sima->mode!=SI_TEXTURE) return 0;
135         if(multires_level1_test()) return 0;    
136         return 1;
137 }
138
139 int is_uv_tface_editing_allowed(void)
140 {
141         if(!G.obedit) error("Enter Edit Mode to perform this action");
142
143         return is_uv_tface_editing_allowed_silent();
144 }
145
146 void get_connected_limit_tface_uv(float *limit)
147 {
148         ImBuf *ibuf= imagewindow_get_ibuf(G.sima);
149         if(ibuf && ibuf->x > 0 && ibuf->y > 0) {
150                 limit[0]= 0.05/(float)ibuf->x;
151                 limit[1]= 0.05/(float)ibuf->y;
152         }
153         else
154                 limit[0]= limit[1]= 0.05/256.0;
155 }
156
157 void be_square_tface_uv(EditMesh *em)
158 {
159         EditFace *efa;
160         MTFace *tface;
161         /* if 1 vertex selected: doit (with the selected vertex) */
162         for (efa= em->faces.first; efa; efa= efa->next) {
163                 if (efa->v4) {
164                         tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
165                         if (simaFaceDraw_Check(efa, tface)) {
166                                 if (simaUVSel_Check(efa, tface, 0)) {
167                                         if( tface->uv[1][0] == tface->uv[2][0] ) {
168                                                 tface->uv[1][1]= tface->uv[0][1];
169                                                 tface->uv[3][0]= tface->uv[0][0];
170                                         }
171                                         else {  
172                                                 tface->uv[1][0]= tface->uv[0][0];
173                                                 tface->uv[3][1]= tface->uv[0][1];
174                                         }
175                                         
176                                 }
177                                 if (simaUVSel_Check(efa, tface, 1)) {
178                                         if( tface->uv[2][1] == tface->uv[3][1] ) {
179                                                 tface->uv[2][0]= tface->uv[1][0];
180                                                 tface->uv[0][1]= tface->uv[1][1];
181                                         }
182                                         else {
183                                                 tface->uv[2][1]= tface->uv[1][1];
184                                                 tface->uv[0][0]= tface->uv[1][0];
185                                         }
186
187                                 }
188                                 if (simaUVSel_Check(efa, tface, 2)) {
189                                         if( tface->uv[3][0] == tface->uv[0][0] ) {
190                                                 tface->uv[3][1]= tface->uv[2][1];
191                                                 tface->uv[1][0]= tface->uv[2][0];
192                                         }
193                                         else {
194                                                 tface->uv[3][0]= tface->uv[2][0];
195                                                 tface->uv[1][1]= tface->uv[2][1];
196                                         }
197                                 }
198                                 if (simaUVSel_Check(efa, tface, 3)) {
199                                         if( tface->uv[0][1] == tface->uv[1][1] ) {
200                                                 tface->uv[0][0]= tface->uv[3][0];
201                                                 tface->uv[2][1]= tface->uv[3][1];
202                                         }
203                                         else  {
204                                                 tface->uv[0][1]= tface->uv[3][1];
205                                                 tface->uv[2][0]= tface->uv[3][0];
206                                         }
207
208                                 }
209                         }
210                 }
211         }
212 }
213
214 void transform_aspect_ratio_tface_uv(float *aspx, float *aspy)
215 {
216         int w, h;
217         float xuser_asp, yuser_asp;
218
219         if(G.sima && G.sima->image) {
220                 image_pixel_aspect(G.sima->image, &xuser_asp, &yuser_asp);
221                 
222                 transform_width_height_tface_uv(&w, &h);
223                 *aspx= (float)w/256.0f * xuser_asp;
224                 *aspy= (float)h/256.0f * yuser_asp;
225         }
226         else {
227                 *aspx= 1.0f;
228                 *aspy= 1.0f;
229         }
230 }
231
232 void transform_width_height_tface_uv(int *width, int *height)
233 {
234         ImBuf *ibuf= imagewindow_get_ibuf(G.sima);
235
236         if(ibuf) {
237                 *width= ibuf->x;
238                 *height= ibuf->y;
239         }
240         else {
241                 *width= 256;
242                 *height= 256;
243         }
244 }
245
246 void mirrormenu_tface_uv(void)
247 {
248         float mat[3][3];
249         short mode= 0;
250         
251         Mat3One(mat);
252
253         if( is_uv_tface_editing_allowed()==0 ) return;
254
255         mode= pupmenu("Mirror%t|X Axis%x1|Y Axis%x2|");
256
257         if(mode==-1) return;
258
259         if (mode == 1) {
260                 initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
261                 BIF_setSingleAxisConstraint(mat[0], " on X axis");
262                 Transform();
263         }
264         else {
265                 initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
266                 BIF_setSingleAxisConstraint(mat[1], " on Y axis");
267                 Transform();
268         }
269
270         BIF_undo_push("Mirror UV");
271 }
272
273 void weld_align_tface_uv(char tool)
274 {
275         EditMesh *em = G.editMesh;
276         EditFace *efa;
277         MTFace *tface;
278         float cent[2], min[2], max[2];
279         
280         if( is_uv_tface_editing_allowed()==0 ) return;
281
282         INIT_MINMAX2(min, max);
283
284         if(tool == 'a') {
285                 for (efa= em->faces.first; efa; efa= efa->next) {
286                         tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
287                         if (simaFaceDraw_Check(efa, tface)) {
288                                 if (simaUVSel_Check(efa, tface, 0))
289                                         DO_MINMAX2(tface->uv[0], min, max)
290                                 if (simaUVSel_Check(efa, tface, 1))
291                                         DO_MINMAX2(tface->uv[1], min, max)
292                                 if (simaUVSel_Check(efa, tface, 2))
293                                         DO_MINMAX2(tface->uv[2], min, max)
294                                 if (efa->v4 && simaUVSel_Check(efa, tface, 3))
295                                         DO_MINMAX2(tface->uv[3], min, max)
296                         }
297                 }
298
299                 tool= (max[0]-min[0] >= max[1]-min[1])? 'y': 'x';
300         }
301
302         cent_tface_uv(cent, 0);
303
304         if(tool == 'x' || tool == 'w') {
305                 for (efa= em->faces.first; efa; efa= efa->next) {
306                         tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
307                         if (simaFaceDraw_Check(efa, tface)) {
308                                 if (simaUVSel_Check(efa, tface, 0))
309                                         tface->uv[0][0]= cent[0];
310                                 if (simaUVSel_Check(efa, tface, 1))
311                                         tface->uv[1][0]= cent[0];
312                                 if (simaUVSel_Check(efa, tface, 2))
313                                         tface->uv[2][0]= cent[0];
314                                 if (efa->v4 && simaUVSel_Check(efa, tface, 3))
315                                         tface->uv[3][0]= cent[0];
316                         }
317                 }
318         }
319
320         if(tool == 'y' || tool == 'w') {
321                 for (efa= em->faces.first; efa; efa= efa->next) {
322                         tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
323                         if (simaFaceDraw_Check(efa, tface)) {
324                                 if (simaUVSel_Check(efa, tface, 0))
325                                         tface->uv[0][1]= cent[1];
326                                 if (simaUVSel_Check(efa, tface, 1))
327                                         tface->uv[1][1]= cent[1];
328                                 if (simaUVSel_Check(efa, tface, 2))
329                                         tface->uv[2][1]= cent[1];
330                                 if (efa->v4 && simaUVSel_Check(efa, tface, 3))
331                                         tface->uv[3][1]= cent[1];
332                         }
333                 }
334         }
335
336         object_uvs_changed(OBACT);
337 }
338
339 // just for averaging UV's
340 typedef struct UVVertAverage {
341         float uv[2];
342         int count;
343 } UVVertAverage;
344
345 void stitch_vert_uv_tface(void)
346 {
347         EditMesh *em = G.editMesh;
348         EditFace *efa;
349         EditVert *eve;
350         MTFace *tface;
351         int count;
352         UVVertAverage *uv_average, *uvav;
353         
354         if( is_uv_tface_editing_allowed()==0 ) return;
355         
356         // index and count verts
357         for (count=0, eve=em->verts.first; eve; count++, eve= eve->next) {
358                 eve->tmp.l = count;
359         }
360         
361         uv_average = MEM_callocN(sizeof(UVVertAverage) * count, "Stitch");
362         
363         // gather uv averages per vert
364         for (efa= em->faces.first; efa; efa= efa->next) {
365                 tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
366                 if (simaFaceDraw_Check(efa, tface)) {
367                         if (simaUVSel_Check(efa, tface, 0)) {
368                                 uvav = uv_average + efa->v1->tmp.l;
369                                 uvav->count++;
370                                 uvav->uv[0] += tface->uv[0][0];
371                                 uvav->uv[1] += tface->uv[0][1];
372                         }
373                         if (simaUVSel_Check(efa, tface, 1)) {
374                                 uvav = uv_average + efa->v2->tmp.l;
375                                 uvav->count++;
376                                 uvav->uv[0] += tface->uv[1][0];
377                                 uvav->uv[1] += tface->uv[1][1];
378                         }
379                         if (simaUVSel_Check(efa, tface, 2)) {
380                                 uvav = uv_average + efa->v3->tmp.l;
381                                 uvav->count++;
382                                 uvav->uv[0] += tface->uv[2][0];
383                                 uvav->uv[1] += tface->uv[2][1];
384                         }
385                         if (efa->v4 && simaUVSel_Check(efa, tface, 3)) {
386                                 uvav = uv_average + efa->v4->tmp.l;
387                                 uvav->count++;
388                                 uvav->uv[0] += tface->uv[3][0];
389                                 uvav->uv[1] += tface->uv[3][1];
390                         }
391                 }
392         }
393         
394         // apply uv welding
395         for (efa= em->faces.first; efa; efa= efa->next) {
396                 tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
397                 if (simaFaceDraw_Check(efa, tface)) {
398                         if (simaUVSel_Check(efa, tface, 0)) {
399                                 uvav = uv_average + efa->v1->tmp.l;
400                                 tface->uv[0][0] = uvav->uv[0]/uvav->count;
401                                 tface->uv[0][1] = uvav->uv[1]/uvav->count;
402                         }
403                         if (simaUVSel_Check(efa, tface, 1)) {
404                                 uvav = uv_average + efa->v2->tmp.l;
405                                 tface->uv[1][0] = uvav->uv[0]/uvav->count;
406                                 tface->uv[1][1] = uvav->uv[1]/uvav->count;
407                         }
408                         if (simaUVSel_Check(efa, tface, 2)) {
409                                 uvav = uv_average + efa->v3->tmp.l;
410                                 tface->uv[2][0] = uvav->uv[0]/uvav->count;
411                                 tface->uv[2][1] = uvav->uv[1]/uvav->count;
412                         }
413                         if (efa->v4 && simaUVSel_Check(efa, tface, 3)) {
414                                 uvav = uv_average + efa->v4->tmp.l;
415                                 tface->uv[3][0] = uvav->uv[0]/uvav->count;
416                                 tface->uv[3][1] = uvav->uv[1]/uvav->count;
417                         }
418                 }
419         }
420         MEM_freeN(uv_average);
421         object_uvs_changed(OBACT);
422 }
423
424 void weld_align_menu_tface_uv(void)
425 {
426         short mode= 0;
427
428         if( is_uv_tface_editing_allowed()==0 ) return;
429
430         mode= pupmenu("Weld/Align%t|Weld%x1|Align Auto%x2|Align X%x3|Align Y%x4");
431
432         if(mode==-1) return;
433         if(mode==1) weld_align_tface_uv('w');
434         else if(mode==2) weld_align_tface_uv('a');
435         else if(mode==3) weld_align_tface_uv('x');
436         else if(mode==4) weld_align_tface_uv('y');
437
438         if(mode==1) BIF_undo_push("Weld UV");
439         else if(ELEM3(mode, 2, 3, 4)) BIF_undo_push("Align UV");
440 }
441
442 void select_invert_tface_uv(void)
443 {
444         EditMesh *em = G.editMesh;
445         EditFace *efa;
446         MTFace *tface;
447         
448         if( is_uv_tface_editing_allowed()==0 ) return;
449
450         if (G.sima->flag & SI_SYNC_UVSEL) {
451                 /* Warning, this is not that good (calling editmode stuff from UV),
452                 TODO look into changing it */
453                 selectswap_mesh();
454                 return;
455         } else {
456                 for (efa= em->faces.first; efa; efa= efa->next) {
457                         tface = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
458                         if (simaFaceDraw_Check(efa, tface)) {
459                                 tface->flag ^= TF_SEL1;
460                                 tface->flag ^= TF_SEL2;
461                                 tface->flag ^= TF_SEL3;
462                                 if(efa->v4) tface->flag ^= TF_SEL4;
463                         }
464                 }
465         }
466         BIF_undo_push("Select Inverse UV");
467
468         allqueue(REDRAWIMAGE, 0);
469 }
470
471 void select_swap_tface_uv(void)
472 {
473         EditMesh *em = G.editMesh;
474         EditFace *efa;
475         MTFace *tface;
476         int sel=0;
477         
478         if( is_uv_tface_editing_allowed()==0 ) return;
479         
480         if (G.sima->flag & SI_SYNC_UVSEL) {
481                 deselectall_mesh();
482                 return;
483         } else {
484                         
485                 for (efa= em->faces.first; efa; efa= efa->next) {
486                         tface = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
487                         if (simaFaceDraw_Check(efa, tface)) {
488                                 if(tface->flag & (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4)) {
489                                         sel= 1;
490                                         break;
491                                 }
492                         }
493                 }
494         
495                 for (efa= em->faces.first; efa; efa= efa->next) {
496                         tface = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
497                         if (simaFaceDraw_Check(efa, tface)) {
498                                 if(efa->v4) {
499                                         if(sel) tface->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
500                                         else tface->flag |= (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
501                                 }
502                                 else {
503                                         if(sel) tface->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
504                                         else tface->flag |= (TF_SEL1+TF_SEL2+TF_SEL3);
505                                 }
506                         }
507                 }
508         }
509         BIF_undo_push("Select swap");
510
511         allqueue(REDRAWIMAGE, 0);
512 }
513
514 static int msel_hit(float *limit, unsigned int *hitarray, unsigned int vertexid, float **uv, float *uv2, int sticky)
515 {
516         int i;
517         for(i=0; i< 4; i++) {
518                 if(hitarray[i] == vertexid) {
519                         if(sticky == 2) {
520                                 if(fabs(uv[i][0]-uv2[0]) < limit[0] &&
521                             fabs(uv[i][1]-uv2[1]) < limit[1])
522                                         return 1;
523                         }
524                         else return 1;
525                 }
526         }
527         return 0;
528 }
529
530 static void find_nearest_uv_edge(MTFace **nearesttf, EditFace **nearestefa, int *nearestedge)
531 {
532         EditMesh *em= G.editMesh;
533         MTFace *tf;
534         EditFace *efa;
535         float mvalf[2], v1[2], v2[2];
536         int i, nverts, mindist, dist, uval1[2], uval2[2];
537         short mval[2];
538
539         getmouseco_areawin(mval);
540         mvalf[0]= mval[0];
541         mvalf[1]= mval[1];
542
543         mindist= 0x7FFFFFF;
544         *nearesttf= NULL;
545         *nearestefa= NULL;
546         *nearestedge= 0;
547         
548         for (efa= em->faces.first; efa; efa= efa->next) {
549                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
550                 if(simaFaceDraw_Check(efa, tf)) {
551                         nverts= efa->v4? 4: 3;
552                         for(i=0; i<nverts; i++) {
553                                 uvco_to_areaco_noclip(tf->uv[i], uval1);
554                                 uvco_to_areaco_noclip(tf->uv[(i+1)%nverts], uval2);
555
556                                 v1[0]= uval1[0];
557                                 v1[1]= uval1[1];
558                                 v2[0]= uval2[0];
559                                 v2[1]= uval2[1];
560
561                                 dist= PdistVL2Dfl(mvalf, v1, v2);
562                                 if (dist < mindist) {
563                                         *nearesttf= tf;
564                                         *nearestefa= efa;
565                                         *nearestedge= i;
566                                         mindist= dist;
567                                 }
568                         }
569                 }
570         }
571 }
572
573 static void find_nearest_tface(MTFace **nearesttf, EditFace **nearestefa)
574 {
575         EditMesh *em= G.editMesh;
576         MTFace *tf;
577         EditFace *efa;
578         int i, nverts, mindist, dist, fcenter[2], uval[2];
579         short mval[2];
580
581         getmouseco_areawin(mval);       
582
583         mindist= 0x7FFFFFF;
584         *nearesttf= NULL;
585         *nearestefa= NULL;
586         
587         for (efa= em->faces.first; efa; efa= efa->next) {
588                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
589                 if (simaFaceDraw_Check(efa, tf)) {
590                         fcenter[0]= fcenter[1]= 0;
591                         nverts= efa->v4? 4: 3;
592                         for(i=0; i<nverts; i++) {
593                                 uvco_to_areaco_noclip(tf->uv[i], uval);
594                                 fcenter[0] += uval[0];
595                                 fcenter[1] += uval[1];
596                         }
597
598                         fcenter[0] /= nverts;
599                         fcenter[1] /= nverts;
600
601                         dist= abs(mval[0]- fcenter[0])+ abs(mval[1]- fcenter[1]);
602                         if (dist < mindist) {
603                                 *nearesttf= tf;
604                                 *nearestefa= efa;
605                                 mindist= dist;
606                         }
607                 }
608         }
609 }
610
611 static int nearest_uv_between(MTFace *tf, int nverts, int id, short *mval, int *uval)
612 {
613         float m[3], v1[3], v2[3], c1, c2;
614         int id1, id2;
615
616         id1= (id+nverts-1)%nverts;
617         id2= (id+nverts+1)%nverts;
618
619         m[0] = (float)(mval[0]-uval[0]);
620         m[1] = (float)(mval[1]-uval[1]);
621         Vec2Subf(v1, tf->uv[id1], tf->uv[id]);
622         Vec2Subf(v2, tf->uv[id2], tf->uv[id]);
623
624         /* m and v2 on same side of v-v1? */
625         c1= v1[0]*m[1] - v1[1]*m[0];
626         c2= v1[0]*v2[1] - v1[1]*v2[0];
627
628         if (c1*c2 < 0.0f)
629                 return 0;
630
631         /* m and v1 on same side of v-v2? */
632         c1= v2[0]*m[1] - v2[1]*m[0];
633         c2= v2[0]*v1[1] - v2[1]*v1[0];
634
635         return (c1*c2 >= 0.0f);
636 }
637
638 void find_nearest_uv(MTFace **nearesttf, EditFace **nearestefa, unsigned int *nearestv, int *nearestuv)
639 {
640         EditMesh *em= G.editMesh;
641         EditFace *efa;
642         MTFace *tf;
643         int i, nverts, mindist, dist, uval[2];
644         short mval[2];
645
646         getmouseco_areawin(mval);       
647
648         mindist= 0x7FFFFFF;
649         if (nearesttf) *nearesttf= NULL;
650         if (nearestefa) *nearestefa= NULL;
651         
652         if (nearestv) {
653                 EditVert *ev;
654                 for (i=0, ev=em->verts.first; ev; ev = ev->next, i++)
655                         ev->tmp.l = i;
656         }
657         
658         for (efa= em->faces.first; efa; efa= efa->next) {
659                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
660                 if (simaFaceDraw_Check(efa, tf)) {
661                         nverts= efa->v4? 4: 3;
662                         for(i=0; i<nverts; i++) {
663                                 uvco_to_areaco_noclip(tf->uv[i], uval);
664                                 dist= abs(mval[0]-uval[0]) + abs(mval[1]-uval[1]);
665
666                                 if (simaUVSel_Check(efa, tf, i))
667                                         dist += 5;
668
669                                 if(dist<=mindist) {
670                                         if(dist==mindist)
671                                                 if (!nearest_uv_between(tf, nverts, i, mval, uval))
672                                                         continue;
673
674                                         mindist= dist;
675                                         *nearestuv= i;
676                                         
677                                         if (nearesttf)          *nearesttf= tf;
678                                         if (nearestefa)         *nearestefa= efa;
679                                         if (nearestv) {
680                                                 if (i==0) *nearestv=  efa->v1->tmp.l;
681                                                 else if (i==1) *nearestv=  efa->v2->tmp.l;
682                                                 else if (i==2) *nearestv=  efa->v3->tmp.l;
683                                                 else *nearestv=  efa->v4->tmp.l;
684                                         }
685                                 }
686                         }
687                 }
688         }
689 }
690
691 void mouse_select_sima(void)
692 {
693         EditMesh *em = G.editMesh;
694         EditFace *efa;
695         MTFace *tf, *nearesttf;
696         EditFace *nearestefa=NULL;
697         int a, selectsticky, edgeloop, actface, nearestuv, nearestedge, i, shift;
698         char sticky= 0;
699         int flush = 0; /* 0 == dont flush, 1 == sel, -1 == desel;  only use when selection sync is enabled */
700         unsigned int hitv[4], nearestv;
701         float *hituv[4], limit[2];
702         
703         if( is_uv_tface_editing_allowed()==0 ) return;
704
705         get_connected_limit_tface_uv(limit);
706         
707         edgeloop= G.qual & LR_ALTKEY;
708         shift= G.qual & LR_SHIFTKEY;
709
710         if (G.sima->flag & SI_SYNC_UVSEL) {
711                 /* copy from mesh */
712                 if (G.scene->selectmode == SCE_SELECT_FACE) {
713                         actface= 1;
714                         sticky= 0;
715                 } else {
716                         actface= G.scene->selectmode & SCE_SELECT_FACE;
717                         sticky= 2;
718                 }
719         } else {
720                 /* normal operation */
721                 actface= G.sima->flag & SI_SELACTFACE;
722                 
723                 switch(G.sima->sticky) {
724                 case SI_STICKY_LOC:
725                         sticky=2;
726                         break;
727                 case SI_STICKY_DISABLE:
728                         sticky=0;
729                         break;
730                 case SI_STICKY_VERTEX:
731                         if(G.qual & LR_CTRLKEY) {
732                                 sticky=0;
733                         } else {  
734                                 sticky=1;
735                         }
736                         break;
737                 }
738         }
739
740         if(edgeloop) {
741                 find_nearest_uv_edge(&nearesttf, &nearestefa, &nearestedge);
742                 if(nearesttf==NULL)
743                         return;
744
745                 select_edgeloop_tface_uv(nearestefa, nearestedge, shift, &flush);
746         }
747         else if(actface) {
748                 find_nearest_tface(&nearesttf, &nearestefa);
749                 if(nearesttf==NULL)
750                         return;
751                 
752                 EM_set_actFace(nearestefa);
753
754                 for (i=0; i<4; i++)
755                         hituv[i]= nearesttf->uv[i];
756
757                 hitv[0]= nearestefa->v1->tmp.l;
758                 hitv[1]= nearestefa->v2->tmp.l;
759                 hitv[2]= nearestefa->v3->tmp.l;
760                 
761                 if (nearestefa->v4)     hitv[3]= nearestefa->v4->tmp.l;
762                 else                            hitv[3]= 0xFFFFFFFF;
763         }
764         else {
765                 find_nearest_uv(&nearesttf, &nearestefa, &nearestv, &nearestuv);
766                 if(nearesttf==NULL)
767                         return;
768
769                 if(sticky) {
770                         for(i=0; i<4; i++)
771                                 hitv[i]= 0xFFFFFFFF;
772                         hitv[nearestuv]= nearestv;
773                         hituv[nearestuv]= nearesttf->uv[nearestuv];
774                 }
775         }
776
777         if(!edgeloop && shift) {
778                 /* (de)select face */
779                 if(actface) {
780                         if(simaFaceSel_Check(nearestefa, nearesttf)) {
781                                 simaFaceSel_UnSet(nearestefa, nearesttf);
782                                 selectsticky= 0;
783                         }
784                         else {
785                                 simaFaceSel_Set(nearestefa, nearesttf);
786                                 selectsticky= 1;
787                         }
788                         flush = -1;
789                 }
790                 /* (de)select uv node */
791                 else {
792                         if (simaUVSel_Check(nearestefa, nearesttf, nearestuv)) {
793                                 simaUVSel_UnSet(nearestefa, nearesttf, nearestuv);
794                                 selectsticky= 0;
795                         }
796                         else {
797                                 simaUVSel_Set(nearestefa, nearesttf, nearestuv);
798                                 selectsticky= 1;
799                         }
800                         flush = 1;
801                 }
802
803                 /* (de)select sticky uv nodes */
804                 if(sticky || actface) {
805                         EditVert *ev;
806                         
807                         for (a=0, ev=em->verts.first; ev; ev = ev->next, a++)
808                                 ev->tmp.l = a;
809                         
810                         /* deselect */
811                         if(selectsticky==0) {
812                                 for (efa= em->faces.first; efa; efa= efa->next) {
813                                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
814                                         if (simaFaceDraw_Check(efa, tf)) {
815                                                 /*if(nearesttf && tf!=nearesttf) tf->flag &=~ TF_ACTIVE;*/ /* TODO - deal with editmesh active face */
816                                                 if (!sticky) continue;
817         
818                                                 if(msel_hit(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
819                                                         simaUVSel_UnSet(efa, tf, 0);
820                                                 if(msel_hit(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
821                                                         simaUVSel_UnSet(efa, tf, 1);
822                                                 if(msel_hit(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
823                                                         simaUVSel_UnSet(efa, tf, 2);
824                                                 if (efa->v4)
825                                                         if(msel_hit(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
826                                                                 simaUVSel_UnSet(efa, tf, 3);
827                                         }
828                                 }
829                                 flush = -1;
830                         }
831                         /* select */
832                         else {
833                                 for (efa= em->faces.first; efa; efa= efa->next) {
834                                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
835                                         if (simaFaceDraw_Check(efa, tf)) {
836                                                 if (!sticky) continue;
837                                                 if(msel_hit(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
838                                                         simaUVSel_Set(efa, tf, 0);
839                                                 if(msel_hit(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
840                                                         simaUVSel_Set(efa, tf, 1);
841                                                 if(msel_hit(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
842                                                         simaUVSel_Set(efa, tf, 2);
843                                                 if (efa->v4)
844                                                         if(msel_hit(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
845                                                                 simaUVSel_Set(efa, tf, 3);
846                                         }
847                                 }
848                                 
849                                 if (actface)
850                                         EM_set_actFace(nearestefa);
851                                 
852                                 flush = 1;
853                         }                       
854                 }
855         }
856         else if(!edgeloop) {
857                 /* select face and deselect other faces */ 
858                 if(actface) {
859                         for (efa= em->faces.first; efa; efa= efa->next) {
860                                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
861                                 simaFaceSel_UnSet(efa, tf);
862                         }
863                         if(nearesttf) {
864                                 simaFaceSel_Set(nearestefa, nearesttf);
865                                 EM_set_actFace(nearestefa);
866                         }
867                                 
868                 }
869
870                 /* deselect uvs, and select sticky uvs */
871                 for (efa= em->faces.first; efa; efa= efa->next) {
872                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
873                         if (simaFaceDraw_Check(efa, tf)) {
874                                 if(!actface) simaFaceSel_UnSet(efa, tf);
875                                 if(!sticky) continue;
876
877                                 if(msel_hit(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
878                                         simaUVSel_Set(efa, tf, 0);
879                                 if(msel_hit(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
880                                         simaUVSel_Set(efa, tf, 1);
881                                 if(msel_hit(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
882                                         simaUVSel_Set(efa, tf, 2);
883                                 if(efa->v4)
884                                         if(msel_hit(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
885                                                 simaUVSel_Set(efa, tf, 3);
886                                 flush= 1;
887                         }
888                 }
889                 
890                 if(!actface) {
891                         simaUVSel_Set(nearestefa, nearesttf, nearestuv);
892                         flush= 1;
893                 }
894         }
895         
896         force_draw(1);
897         
898         if (G.sima->flag & SI_SYNC_UVSEL) {
899                 /* flush for mesh selection */
900                 if (G.scene->selectmode != SCE_SELECT_FACE) {
901                         if (flush==1)           EM_select_flush();
902                         else if (flush==-1)     EM_deselect_flush();
903                 }
904                 allqueue(REDRAWVIEW3D, 0); /* mesh selection has changed */
905         }
906         
907         BIF_undo_push("Select UV");
908         rightmouse_transform();
909 }
910
911 void borderselect_sima(short whichuvs)
912 {
913         EditMesh *em = G.editMesh;
914         EditFace *efa;
915         MTFace *tface;
916         rcti rect;
917         rctf rectf;
918         int val, ok = 1;
919         short mval[2], select;
920
921         if( is_uv_tface_editing_allowed()==0) return;
922
923         val= get_border(&rect, 3);
924         select = (val==LEFTMOUSE) ? 1 : 0; 
925         
926         if(val) {
927                 mval[0]= rect.xmin;
928                 mval[1]= rect.ymin;
929                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
930                 mval[0]= rect.xmax;
931                 mval[1]= rect.ymax;
932                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
933                 
934                 if (draw_uvs_face_check() && whichuvs != UV_SELECT_PINNED) {
935                         float cent[2];
936                         ok = 0;
937                         for (efa= em->faces.first; efa; efa= efa->next) {
938                                 /* assume not touched */
939                                 efa->tmp.l = 0;
940                                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
941                                 if (simaFaceDraw_Check(efa, tface)) {
942                                         uv_center(tface->uv, cent, (void *)efa->v4);
943                                         if(BLI_in_rctf(&rectf, cent[0], cent[1])) {
944                                                 efa->tmp.l = ok = 1;
945                                         }
946                                 }
947                         }
948                         /* (de)selects all tagged faces and deals with sticky modes */
949                         if (ok)
950                                 uvface_setsel__internal(select);
951                 } else {
952                         for (efa= em->faces.first; efa; efa= efa->next) {
953                                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
954                                 if (simaFaceDraw_Check(efa, tface)) {
955                                         if (whichuvs == UV_SELECT_ALL || (G.sima->flag & SI_SYNC_UVSEL) ) {
956                                                 /* SI_SYNC_UVSEL - cant do pinned selection */
957                                                 if(BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) {
958                                                         if(select)      simaUVSel_Set(efa, tface, 0);
959                                                         else            simaUVSel_UnSet(efa, tface, 0);
960                                                 }
961                                                 if(BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) {
962                                                         if(select)      simaUVSel_Set(efa, tface, 1);
963                                                         else            simaUVSel_UnSet(efa, tface, 1);
964                                                 }
965                                                 if(BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) {
966                                                         if(select)      simaUVSel_Set(efa, tface, 2);
967                                                         else            simaUVSel_UnSet(efa, tface, 2);
968                                                 }
969                                                 if(efa->v4 && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) {
970                                                         if(select)      simaUVSel_Set(efa, tface, 3);
971                                                         else            simaUVSel_UnSet(efa, tface, 3);
972                                                 }
973                                         } else if (whichuvs == UV_SELECT_PINNED) {
974                                                 if ((tface->unwrap & TF_PIN1) && 
975                                                         BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) {
976                                                         
977                                                         if(select)      simaUVSel_Set(efa, tface, 0);
978                                                         else            simaUVSel_UnSet(efa, tface, 0);
979                                                 }
980                                                 if ((tface->unwrap & TF_PIN2) && 
981                                                         BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) {
982                                                         
983                                                         if(select)      simaUVSel_Set(efa, tface, 1);
984                                                         else            simaUVSel_UnSet(efa, tface, 1);
985                                                 }
986                                                 if ((tface->unwrap & TF_PIN3) && 
987                                                         BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) {
988                                                         
989                                                         if(select)      simaUVSel_Set(efa, tface, 2);
990                                                         else            simaUVSel_UnSet(efa, tface, 2);
991                                                 }
992                                                 if ((efa->v4) && (tface->unwrap & TF_PIN4) && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) {
993                                                         if(select)      simaUVSel_Set(efa, tface, 3);
994                                                         else            simaUVSel_UnSet(efa, tface, 3);
995                                                 }
996                                         }
997                                 }
998                         }
999                 }
1000                 if (ok) {
1001                         /* make sure newly selected vert selection is updated*/
1002                         if (G.sima->flag & SI_SYNC_UVSEL) {
1003                                 if (G.scene->selectmode != SCE_SELECT_FACE) {
1004                                         if (select)     EM_select_flush();
1005                                         else            EM_deselect_flush();
1006                                 }
1007                         }
1008                         allqueue(REDRAWVIEW3D, 0); /* mesh selection has changed */
1009                         
1010                         BIF_undo_push("Border select UV");
1011                         scrarea_queue_winredraw(curarea);
1012                 }
1013         }
1014 }
1015
1016 int snap_uv_sel_to_curs(void)
1017 {
1018         EditMesh *em = G.editMesh;
1019         EditFace *efa;
1020         MTFace *tface;
1021         short change = 0;
1022
1023         for (efa= em->faces.first; efa; efa= efa->next) {
1024                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1025                 if (simaFaceDraw_Check(efa, tface)) {
1026                         if (simaUVSel_Check(efa, tface, 0))             VECCOPY2D(tface->uv[0], G.v2d->cursor);
1027                         if (simaUVSel_Check(efa, tface, 1))             VECCOPY2D(tface->uv[1], G.v2d->cursor);
1028                         if (simaUVSel_Check(efa, tface, 2))             VECCOPY2D(tface->uv[2], G.v2d->cursor);
1029                         if (efa->v4)
1030                                 if (simaUVSel_Check(efa, tface, 3))     VECCOPY2D(tface->uv[3], G.v2d->cursor);
1031                         change = 1;
1032                 }
1033         }
1034         return change;
1035 }
1036
1037 int snap_uv_sel_to_adj_unsel(void)
1038 {
1039         EditMesh *em = G.editMesh;
1040         EditFace *efa;
1041         EditVert *eve;
1042         MTFace *tface;
1043         short change = 0;
1044         int count = 0;
1045         float *coords;
1046         short *usercount, users;
1047         
1048         /* set all verts to -1 : an unused index*/
1049         for (eve= em->verts.first; eve; eve= eve->next)
1050                 eve->tmp.l=-1;
1051         
1052         /* index every vert that has a selected UV using it, but only once so as to
1053          * get unique indicies and to count how much to malloc */
1054         for (efa= em->faces.first; efa; efa= efa->next) {
1055                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1056                 if (simaFaceDraw_Check(efa, tface)) {
1057                         if (simaUVSel_Check(efa, tface, 0) && efa->v1->tmp.l==-1)               efa->v1->tmp.l= count++;
1058                         if (simaUVSel_Check(efa, tface, 1) && efa->v2->tmp.l==-1)               efa->v2->tmp.l= count++;
1059                         if (simaUVSel_Check(efa, tface, 2) && efa->v3->tmp.l==-1)               efa->v3->tmp.l= count++;
1060                         if (efa->v4)
1061                                 if (simaUVSel_Check(efa, tface, 3) && efa->v4->tmp.l==-1)       efa->v4->tmp.l= count++;
1062                         change = 1;
1063                         
1064                         /* optional speedup */
1065                         efa->tmp.p = tface;
1066                 } else {
1067                         efa->tmp.p = NULL;
1068                 }
1069         }
1070         
1071         coords = MEM_callocN(sizeof(float)*count*2, "snap to adjacent coords");
1072         usercount = MEM_callocN(sizeof(short)*count, "snap to adjacent counts");
1073         
1074         /* add all UV coords from visible, unselected UV coords as well as counting them to average later */
1075         for (efa= em->faces.first; efa; efa= efa->next) {
1076 //              tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1077 //              if (simaFaceDraw_Check(efa, tface)) {
1078                 if ((tface=(MTFace *)efa->tmp.p)) {
1079                         
1080                         /* is this an unselected UV we can snap to? */
1081                         if (efa->v1->tmp.l >= 0 && (!simaUVSel_Check(efa, tface, 0))) {
1082                                 coords[efa->v1->tmp.l*2] +=             tface->uv[0][0];
1083                                 coords[(efa->v1->tmp.l*2)+1] += tface->uv[0][1];
1084                                 usercount[efa->v1->tmp.l]++;
1085                                 change = 1;
1086                         }
1087                         if (efa->v2->tmp.l >= 0 && (!simaUVSel_Check(efa, tface, 1))) {
1088                                 coords[efa->v2->tmp.l*2] +=             tface->uv[1][0];
1089                                 coords[(efa->v2->tmp.l*2)+1] += tface->uv[1][1];
1090                                 usercount[efa->v2->tmp.l]++;
1091                                 change = 1;
1092                         }
1093                         if (efa->v3->tmp.l >= 0 && (!simaUVSel_Check(efa, tface, 2))) {
1094                                 coords[efa->v3->tmp.l*2] +=             tface->uv[2][0];
1095                                 coords[(efa->v3->tmp.l*2)+1] += tface->uv[2][1];
1096                                 usercount[efa->v3->tmp.l]++;
1097                                 change = 1;
1098                         }
1099                         
1100                         if (efa->v4) {
1101                                 if (efa->v4->tmp.l >= 0 && (!simaUVSel_Check(efa, tface, 3))) {
1102                                         coords[efa->v4->tmp.l*2] +=             tface->uv[3][0];
1103                                         coords[(efa->v4->tmp.l*2)+1] += tface->uv[3][1];
1104                                         usercount[efa->v4->tmp.l]++;
1105                                         change = 1;
1106                                 }
1107                         }
1108                 }
1109         }
1110         
1111         /* no other verts selected, bail out */
1112         if (!change) {
1113                 MEM_freeN(coords);
1114                 MEM_freeN(usercount);
1115                 return change;
1116         }
1117         
1118         /* copy the averaged unselected UVs back to the selected UVs */
1119         for (efa= em->faces.first; efa; efa= efa->next) {
1120 //              tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1121 //              if (simaFaceDraw_Check(efa, tface)) {
1122                 if ((tface=(MTFace *)efa->tmp.p)) {
1123                         
1124                         if (    simaUVSel_Check(efa, tface, 0) &&
1125                                         efa->v1->tmp.l >= 0 &&
1126                                         (users = usercount[efa->v1->tmp.l])
1127                         ) {
1128                                 tface->uv[0][0] = coords[efa->v1->tmp.l*2]              / users;
1129                                 tface->uv[0][1] = coords[(efa->v1->tmp.l*2)+1]  / users;
1130                         }
1131
1132                         if (    simaUVSel_Check(efa, tface, 1) &&
1133                                         efa->v2->tmp.l >= 0 &&
1134                                         (users = usercount[efa->v2->tmp.l])
1135                         ) {
1136                                 tface->uv[1][0] = coords[efa->v2->tmp.l*2]              / users;
1137                                 tface->uv[1][1] = coords[(efa->v2->tmp.l*2)+1]  / users;
1138                         }
1139                         
1140                         if (    simaUVSel_Check(efa, tface, 2) &&
1141                                         efa->v3->tmp.l >= 0 &&
1142                                         (users = usercount[efa->v3->tmp.l])
1143                         ) {
1144                                 tface->uv[2][0] = coords[efa->v3->tmp.l*2]              / users;
1145                                 tface->uv[2][1] = coords[(efa->v3->tmp.l*2)+1]  / users;
1146                         }
1147                         
1148                         if (efa->v4) {
1149                                 if (    simaUVSel_Check(efa, tface, 3) &&
1150                                                 efa->v4->tmp.l >= 0 &&
1151                                                 (users = usercount[efa->v4->tmp.l])
1152                                 ) {
1153                                         tface->uv[3][0] = coords[efa->v4->tmp.l*2]              / users;
1154                                         tface->uv[3][1] = coords[(efa->v4->tmp.l*2)+1]  / users;
1155                                 }
1156                         }
1157                 }
1158         }
1159         
1160         MEM_freeN(coords);
1161         MEM_freeN(usercount);
1162         return change;
1163 }
1164
1165 void snap_coord_to_pixel(float *uvco, float w, float h)
1166 {
1167         uvco[0] = ((float) ((int)((uvco[0]*w) + 0.5))) / w;  
1168         uvco[1] = ((float) ((int)((uvco[1]*h) + 0.5))) / h;  
1169 }
1170
1171 int snap_uv_sel_to_pixels(void) /* warning, sanity checks must alredy be done */
1172 {
1173         EditMesh *em = G.editMesh;
1174         EditFace *efa;
1175         MTFace *tface;
1176         int wi, hi;
1177         float w, h;
1178         short change = 0;
1179
1180         transform_width_height_tface_uv(&wi, &hi);
1181         w = (float)wi;
1182         h = (float)hi;
1183         
1184         for (efa= em->faces.first; efa; efa= efa->next) {
1185                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1186                 if (simaFaceDraw_Check(efa, tface)) {
1187                         if (simaUVSel_Check(efa, tface, 0)) snap_coord_to_pixel(tface->uv[0], w, h);
1188                         if (simaUVSel_Check(efa, tface, 1)) snap_coord_to_pixel(tface->uv[1], w, h);
1189                         if (simaUVSel_Check(efa, tface, 2)) snap_coord_to_pixel(tface->uv[2], w, h);
1190                         if (efa->v4)
1191                                 if (simaUVSel_Check(efa, tface, 3)) snap_coord_to_pixel(tface->uv[3], w, h);
1192                         change = 1;
1193                 }
1194         }
1195         return change;
1196 }
1197
1198 void snap_uv_curs_to_pixels(void)
1199 {
1200         int wi, hi;
1201         float w, h;
1202
1203         transform_width_height_tface_uv(&wi, &hi);
1204         w = (float)wi;
1205         h = (float)hi;
1206         snap_coord_to_pixel(G.v2d->cursor, w, h);
1207 }
1208
1209 int snap_uv_curs_to_sel(void)
1210 {
1211         if( is_uv_tface_editing_allowed()==0 ) return 0;
1212         return cent_tface_uv(G.v2d->cursor, 0);
1213 }
1214
1215 void snap_menu_sima(void)
1216 {
1217         short event;
1218         if( is_uv_tface_editing_allowed()==0 || !G.v2d) return; /* !G.v2d should never happen */
1219         
1220         event = pupmenu("Snap %t|Selection -> Pixels%x1|Selection -> Cursor%x2|Selection -> Adjacent Unselected%x3|Cursor -> Pixel%x4|Cursor -> Selection%x5");
1221         switch (event) {
1222                 case 1:
1223                     if (snap_uv_sel_to_pixels()) {
1224                         BIF_undo_push("Snap UV Selection to Pixels");
1225                         object_uvs_changed(OBACT);
1226                     }
1227                     break;
1228                 case 2:
1229                     if (snap_uv_sel_to_curs()) {
1230                         BIF_undo_push("Snap UV Selection to Cursor");
1231                         object_uvs_changed(OBACT);
1232                     }
1233                     break;
1234                 case 3:
1235                     if (snap_uv_sel_to_adj_unsel()) {
1236                         BIF_undo_push("Snap UV Selection to Cursor");
1237                         object_uvs_changed(OBACT);
1238                     }
1239                     break;
1240                 case 4:
1241                     snap_uv_curs_to_pixels();
1242                     scrarea_queue_winredraw(curarea);
1243                     break;
1244                 case 5:
1245                     if (snap_uv_curs_to_sel())
1246                         allqueue(REDRAWIMAGE, 0);
1247                     break;
1248         }
1249 }
1250
1251
1252 /** This is an ugly function to set the Tface selection flags depending
1253   * on whether its UV coordinates are inside the normalized 
1254   * area with radius rad and offset offset. These coordinates must be
1255   * normalized to 1.0 
1256   * Just for readability...
1257   */
1258
1259 void sel_uvco_inside_radius(short sel, EditFace *efa, MTFace *tface, int index, float *offset, float *ell, short select_index)
1260 {
1261         // normalized ellipse: ell[0] = scaleX,
1262         //                        [1] = scaleY
1263
1264         float *uv = tface->uv[index];
1265         float x, y, r2;
1266
1267         x = (uv[0] - offset[0]) * ell[0];
1268         y = (uv[1] - offset[1]) * ell[1];
1269
1270         r2 = x * x + y * y;
1271         if (r2 < 1.0) {
1272                 if (sel == LEFTMOUSE)   simaUVSel_Set(efa, tface, select_index);
1273                 else                                    simaUVSel_UnSet(efa, tface, select_index);
1274         }
1275 }
1276
1277 // see below:
1278 /** gets image dimensions of the 2D view 'v' */
1279 static void getSpaceImageDimension(SpaceImage *sima, float *xy)
1280 {
1281         ImBuf *ibuf= imagewindow_get_ibuf(G.sima);
1282
1283         if (ibuf) {
1284                 xy[0] = ibuf->x * sima->zoom;
1285                 xy[1] = ibuf->y * sima->zoom;
1286         } else {
1287                 xy[0] = 256 * sima->zoom;
1288                 xy[1] = 256 * sima->zoom;
1289         }
1290 }
1291
1292 /** Callback function called by circle_selectCB to enable 
1293   * brush select in UV editor.
1294   */
1295
1296 void uvedit_selectionCB(short selecting, Object *editobj, short *mval, float rad) 
1297 {
1298         EditMesh *em = G.editMesh;
1299         EditFace *efa;
1300         float offset[2];
1301         MTFace *tface;
1302         float ellipse[2]; // we need to deal with ellipses, as
1303                           // non square textures require for circle
1304                                           // selection. this ellipse is normalized; r = 1.0
1305
1306         getSpaceImageDimension(curarea->spacedata.first, ellipse);
1307         ellipse[0] /= rad;
1308         ellipse[1] /= rad;
1309
1310         areamouseco_to_ipoco(G.v2d, mval, &offset[0], &offset[1]);
1311         
1312         if (selecting) {
1313                 for (efa= em->faces.first; efa; efa= efa->next) {
1314                         tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1315                         sel_uvco_inside_radius(selecting, efa, tface, 0, offset, ellipse, 0);
1316                         sel_uvco_inside_radius(selecting, efa, tface, 1, offset, ellipse, 1);
1317                         sel_uvco_inside_radius(selecting, efa, tface, 2, offset, ellipse, 2);
1318                         if (efa->v4)
1319                                 sel_uvco_inside_radius(selecting, efa, tface, 3, offset, ellipse, 3);
1320                 }
1321
1322                 if(G.f & G_DRAWFACES) { /* full redraw only if necessary */
1323                         draw_sel_circle(0, 0, 0, 0, 0); /* signal */
1324                         force_draw(0);
1325                 }
1326                 else { /* force_draw() is no good here... */
1327                         glDrawBuffer(GL_FRONT);
1328                         draw_uvs_sima();
1329                         bglFlush();
1330                         glDrawBuffer(GL_BACK);
1331                 }
1332                 
1333                 
1334                 if (selecting == LEFTMOUSE)     EM_select_flush();
1335                 else                                            EM_deselect_flush();
1336                 
1337                 if (G.sima->lock && (G.sima->flag & SI_SYNC_UVSEL))
1338                         force_draw_plus(SPACE_VIEW3D, 0);
1339         }
1340 }
1341
1342
1343 void mouseco_to_curtile(void)
1344 {
1345         float fx, fy;
1346         short mval[2];
1347         
1348         if( is_uv_tface_editing_allowed()==0) return;
1349
1350         if(G.sima->image && G.sima->image->tpageflag & IMA_TILES) {
1351                 
1352                 G.sima->flag |= SI_EDITTILE;
1353                 
1354                 while(get_mbut()&L_MOUSE) {
1355                         
1356                         calc_image_view(G.sima, 'f');
1357                         
1358                         getmouseco_areawin(mval);
1359                         areamouseco_to_ipoco(G.v2d, mval, &fx, &fy);
1360
1361                         if(fx>=0.0 && fy>=0.0 && fx<1.0 && fy<1.0) {
1362                         
1363                                 fx= (fx)*G.sima->image->xrep;
1364                                 fy= (fy)*G.sima->image->yrep;
1365                                 
1366                                 mval[0]= fx;
1367                                 mval[1]= fy;
1368                                 
1369                                 G.sima->curtile= mval[1]*G.sima->image->xrep + mval[0];
1370                         }
1371
1372                         scrarea_do_windraw(curarea);
1373                         screen_swapbuffers();
1374                 }
1375                 
1376                 G.sima->flag &= ~SI_EDITTILE;
1377
1378                 image_set_tile(G.sima, 2);
1379
1380                 allqueue(REDRAWVIEW3D, 0);
1381                 scrarea_queue_winredraw(curarea);
1382         }
1383 }
1384
1385 /* Could be used for other 2D views also */
1386 void mouseco_to_cursor_sima(void)
1387 {
1388         short mval[2];
1389         getmouseco_areawin(mval);
1390         areamouseco_to_ipoco(G.v2d, mval, &G.v2d->cursor[0], &G.v2d->cursor[1]);
1391         scrarea_queue_winredraw(curarea);
1392 }
1393
1394 void stitch_limit_uv_tface(void)
1395 {
1396         MTFace *tf;
1397         int a, vtot;
1398         float newuv[2], limit[2], pixellimit;
1399         UvMapVert *vlist, *iterv;
1400         EditMesh *em = G.editMesh;
1401         EditVert *ev;
1402         EditFace *efa;
1403         
1404         struct UvVertMap *vmap;
1405         
1406         
1407         if(is_uv_tface_editing_allowed()==0)
1408                 return;
1409         if(G.sima->flag & SI_SYNC_UVSEL) {
1410                 error("Can't stitch when Sync Mesh Selection is enabled");
1411                 return;
1412         }
1413         
1414         pixellimit= 20.0f;
1415         add_numbut(0, NUM|FLO, "Limit:", 0.1, 1000.0, &pixellimit, NULL);
1416         if (!do_clever_numbuts("Stitch UVs", 1, REDRAW))
1417                 return;
1418
1419         if(G.sima->image) {
1420                 ImBuf *ibuf= imagewindow_get_ibuf(G.sima);
1421
1422                 if(ibuf && ibuf->x > 0 && ibuf->y > 0) {
1423                         limit[0]= pixellimit/(float)ibuf->x;
1424                         limit[1]= pixellimit/(float)ibuf->y;
1425                 }
1426                 else
1427                         limit[0]= limit[1]= pixellimit/256.0;
1428         }
1429         else
1430                 limit[0]= limit[1]= pixellimit/256.0;
1431
1432         /*vmap= make_uv_vert_map(me->mface, tf, me->totface, me->totvert, 1, limit);*/
1433         EM_init_index_arrays(0, 0, 1);
1434         vmap= make_uv_vert_map_EM(1, 0, limit);
1435         if(vmap == NULL)
1436                 return;
1437
1438         for(a=0, ev= em->verts.first; ev; a++, ev= ev->next) {
1439                 vlist= get_uv_map_vert_EM(vmap, a);
1440
1441                 while(vlist) {
1442                         newuv[0]= 0; newuv[1]= 0;
1443                         vtot= 0;
1444
1445                         for(iterv=vlist; iterv; iterv=iterv->next) {
1446                                 if((iterv != vlist) && iterv->separate)
1447                                         break;
1448                                 efa = EM_get_face_for_index(iterv->f);
1449                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1450                                 
1451                                 if (tf->flag & TF_SEL_MASK(iterv->tfindex)) {
1452                                         newuv[0] += tf->uv[iterv->tfindex][0];
1453                                         newuv[1] += tf->uv[iterv->tfindex][1];
1454                                         vtot++;
1455                                 }
1456                         }
1457
1458                         if (vtot > 1) {
1459                                 newuv[0] /= vtot; newuv[1] /= vtot;
1460
1461                                 for(iterv=vlist; iterv; iterv=iterv->next) {
1462                                         if((iterv != vlist) && iterv->separate)
1463                                                 break;
1464                                         efa = EM_get_face_for_index(iterv->f);
1465                                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1466                                         if (tf->flag & TF_SEL_MASK(iterv->tfindex)) {
1467                                                 tf->uv[iterv->tfindex][0]= newuv[0];
1468                                                 tf->uv[iterv->tfindex][1]= newuv[1];
1469                                         }
1470                                 }
1471                         }
1472                         vlist= iterv;
1473                 }
1474         }
1475
1476         free_uv_vert_map_EM(vmap);
1477         EM_free_index_arrays();
1478         
1479         if(G.sima->flag & SI_BE_SQUARE) be_square_tface_uv(em);
1480
1481         BIF_undo_push("Stitch UV");
1482
1483         object_uvs_changed(OBACT);
1484 }
1485
1486 void select_linked_tface_uv(int mode) /* TODO */
1487 {
1488         EditMesh *em= G.editMesh;
1489         EditFace *efa, *nearestefa=NULL;
1490         MTFace *tf, *nearesttf=NULL;
1491         UvVertMap *vmap;
1492         UvMapVert *vlist, *iterv, *startv;
1493         unsigned int *stack, stacksize= 0, nearestv;
1494         char *flag;
1495         int a, nearestuv, i, nverts, j;
1496         float limit[2];
1497         if(is_uv_tface_editing_allowed()==0)
1498                 return;
1499
1500         if(G.sima->flag & SI_SYNC_UVSEL) {
1501                 error("Can't select linked when Sync Mesh Selection is enabled");
1502                 return;
1503         }
1504         
1505         if (mode == 2) {
1506                 nearesttf= NULL;
1507                 nearestuv= 0;
1508         }
1509         if (mode!=2) {
1510                 find_nearest_uv(&nearesttf, &nearestefa, &nearestv, &nearestuv);
1511                 if(nearesttf==NULL)
1512                         return;
1513         }
1514
1515         get_connected_limit_tface_uv(limit);
1516         vmap= make_uv_vert_map_EM(1, 1, limit);
1517         if(vmap == NULL)
1518                 return;
1519
1520         stack= MEM_mallocN(sizeof(*stack)* BLI_countlist(&em->faces), "UvLinkStack");
1521         flag= MEM_callocN(sizeof(*flag)*BLI_countlist(&em->faces), "UvLinkFlag");
1522
1523         if (mode == 2) {
1524                 for (a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
1525                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1526                         if (simaFaceDraw_Check(efa, tf)) {
1527                                 if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) {
1528                                         stack[stacksize]= a;
1529                                         stacksize++;
1530                                         flag[a]= 1;
1531                                 }
1532                         }
1533                 }
1534         } else {
1535                 for (a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
1536                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1537                         if(tf == nearesttf) {
1538                                 stack[stacksize]= a;
1539                                 stacksize++;
1540                                 flag[a]= 1;
1541                                 break;
1542                         }
1543                 }
1544         }
1545
1546         while(stacksize > 0) {
1547                 stacksize--;
1548                 a= stack[stacksize];
1549                 
1550                 for (j=0, efa= em->faces.first; efa; efa= efa->next, j++) {
1551                         if (j==a) {
1552                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1553                                 break;
1554                         }
1555                 }
1556
1557                 nverts= efa->v4? 4: 3;
1558
1559                 for(i=0; i<nverts; i++) {
1560                         /* make_uv_vert_map_EM sets verts tmp.l to the indicies */
1561                         vlist= get_uv_map_vert_EM(vmap, (*(&efa->v1 + i))->tmp.l);
1562                         
1563                         startv= vlist;
1564
1565                         for(iterv=vlist; iterv; iterv=iterv->next) {
1566                                 if(iterv->separate)
1567                                         startv= iterv;
1568                                 if(iterv->f == a)
1569                                         break;
1570                         }
1571
1572                         for(iterv=startv; iterv; iterv=iterv->next) {
1573                                 if((startv != iterv) && (iterv->separate))
1574                                         break;
1575                                 else if(!flag[iterv->f]) {
1576                                         flag[iterv->f]= 1;
1577                                         stack[stacksize]= iterv->f;;
1578                                         stacksize++;
1579                                 }
1580                         }
1581                 }
1582         }
1583
1584         if(mode==0 || mode==2) {
1585                 for (a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
1586                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1587                         if(flag[a])
1588                                 tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1589                         else
1590                                 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1591                 }
1592         }
1593         else if(mode==1) {
1594                 for (a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
1595                         if(flag[a]) {
1596                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1597                                 if (efa->v4) {
1598                                         if((tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)))
1599                                                 break;
1600                                 }
1601                                 else if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
1602                                         break;
1603                         }
1604                 }
1605
1606                 if (efa) {
1607                         for (a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
1608                                 if(flag[a]) {
1609                                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1610                                         tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1611                                 }
1612                         }
1613                 }
1614                 else {
1615                         for (a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
1616                                 if(flag[a]) {
1617                                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1618                                         tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1619                                 }
1620                         }
1621                 }
1622         }
1623         
1624         MEM_freeN(stack);
1625         MEM_freeN(flag);
1626         free_uv_vert_map_EM(vmap);
1627
1628         BIF_undo_push("Select linked UV");
1629         scrarea_queue_winredraw(curarea);
1630 }
1631
1632 void unlink_selection(void)
1633 {
1634         EditMesh *em= G.editMesh;
1635         EditFace *efa;
1636         MTFace *tface;
1637
1638         if( is_uv_tface_editing_allowed()==0 ) return;
1639
1640         if(G.sima->flag & SI_SYNC_UVSEL) {
1641                 error("Can't select unlinked when Sync Mesh Selection is enabled");
1642                 return;
1643         }
1644         
1645         for (efa= em->faces.first; efa; efa= efa->next) {
1646                 tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1647                 if (simaFaceDraw_Check(efa, tface)) {
1648                         if(efa->v4) {
1649                                 if(~tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4))
1650                                         tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1651                         } else {
1652                                 if(~tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
1653                                         tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3);
1654                         }
1655                 }
1656         }
1657         
1658         BIF_undo_push("Unlink UV selection");
1659         scrarea_queue_winredraw(curarea);
1660 }
1661
1662 /* this function sets the selection on tagged faces
1663  * This is needed because setting the selection on a face is done in
1664  * a number of places but it also needs to respect the sticky modes
1665  * for the UV verts - dealing with the sticky modes is best done in a seperate function
1666  * 
1667  * de-selects faces that have been tagged on efa->tmp.l 
1668  */
1669 void uvface_setsel__internal(short select)
1670 {
1671         
1672         /* All functions calling this should call
1673          * draw_uvs_face_check() 
1674          */
1675         
1676                 
1677         /* selecting UV Faces with some modes requires us to change 
1678          * the selection in other faces (depending on the stickt mode)
1679          * 
1680          * This only needs to be done when the Mesh is not used for selection
1681          * (So for sticky modes - vertex or location based)
1682          * */
1683         
1684         EditMesh *em = G.editMesh;
1685         EditFace *efa;
1686         MTFace *tf;
1687         int nverts, i;
1688         
1689         if ((G.sima->flag & SI_SYNC_UVSEL)==0 && G.sima->sticky == SI_STICKY_VERTEX) {
1690                 /* tag all verts as untouched,
1691                  * then touch the ones that have a face center in the loop
1692                  * and select all MTFace UV's that use a touched vert */
1693                 
1694                 EditVert *eve;
1695                 
1696                 for (eve= em->verts.first; eve; eve= eve->next)
1697                         eve->tmp.l = 0;
1698                 
1699                 for (efa= em->faces.first; efa; efa= efa->next) {
1700                         if (efa->tmp.l) {
1701                                 if (efa->v4) {
1702                                         efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= efa->v4->tmp.l=1;
1703                                 } else {
1704                                         efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= 1;
1705                                 }
1706                         }
1707                 }
1708                 /* now select tagged verts */
1709                 for (efa= em->faces.first; efa; efa= efa->next) {
1710                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);               
1711                         nverts= efa->v4? 4: 3;
1712                         for(i=0; i<nverts; i++) {
1713                                 if ((*(&efa->v1 + i))->tmp.l) {
1714                                         if (select) {
1715                                                 simaUVSel_Set(efa, tf, i);
1716                                         } else {
1717                                                 simaUVSel_UnSet(efa, tf, i);
1718                                         }
1719                                 }
1720                         }
1721                 }
1722         } else if ((G.sima->flag & SI_SYNC_UVSEL)==0 && G.sima->sticky == SI_STICKY_LOC) {
1723                 EditFace *efa_vlist;
1724                 MTFace *tf_vlist;
1725                 UvMapVert *vlist, *start_vlist=NULL, *vlist_iter;
1726                 struct UvVertMap *vmap;
1727                 float limit[2];
1728                 int efa_index;
1729                 //EditVert *eve; /* removed vert counting for now */ 
1730                 //int a;
1731                 
1732                 get_connected_limit_tface_uv(limit);
1733                 
1734                 EM_init_index_arrays(0, 0, 1);
1735                 vmap= make_uv_vert_map_EM(0, 0, limit);
1736                 
1737                 /* verts are numbered above in make_uv_vert_map_EM, make sure this stays true! */
1738                 /*for (a=0, eve= em->verts.first; eve; a++, eve= eve->next)
1739                         eve->tmp.l = a; */
1740                 
1741                 if(vmap == NULL)
1742                         return;
1743                 
1744                 for (efa_index=0, efa= em->faces.first; efa; efa_index++, efa= efa->next) {
1745                         if (efa->tmp.l) {
1746                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1747                                 nverts= efa->v4? 4: 3;
1748                                 for(i=0; i<nverts; i++) {
1749                                         if (select) {
1750                                                 simaUVSel_Set(efa, tf, i);
1751                                         } else {
1752                                                 simaUVSel_UnSet(efa, tf, i);
1753                                         }
1754                                         
1755                                         vlist= vlist_iter= get_uv_map_vert_EM(vmap, (*(&efa->v1 + i))->tmp.l);
1756                                         
1757                                         while (vlist_iter) {
1758                                                 if (vlist_iter->separate)
1759                                                         start_vlist = vlist_iter;
1760                                                 
1761                                                 if (efa_index == vlist_iter->f) {
1762                                                         break;
1763                                                 }
1764                                                 vlist_iter = vlist_iter->next;
1765                                         }
1766                                 
1767                                         vlist_iter = start_vlist;
1768                                         while (vlist_iter) {
1769                                                 
1770                                                 if (vlist_iter != start_vlist && vlist_iter->separate)
1771                                                         break;
1772                                                 
1773                                                 if (efa_index != vlist_iter->f) {
1774                                                         efa_vlist = EM_get_face_for_index(vlist_iter->f);
1775                                                         tf_vlist = CustomData_em_get(&em->fdata, efa_vlist->data, CD_MTFACE);
1776                                                         
1777                                                         if (select) {
1778                                                                 simaUVSel_Set(efa_vlist, tf_vlist, vlist_iter->tfindex);
1779                                                         } else {
1780                                                                 simaUVSel_UnSet(efa_vlist, tf_vlist, vlist_iter->tfindex);
1781                                                         }
1782                                                 }
1783                                                 vlist_iter = vlist_iter->next;
1784                                         }
1785                                 }
1786                         }
1787                 }
1788                 EM_free_index_arrays();
1789                 free_uv_vert_map_EM(vmap);
1790                 
1791         } else { /* SI_STICKY_DISABLE or G.sima->flag & SI_SYNC_UVSEL */
1792                 for (efa= em->faces.first; efa; efa= efa->next) {
1793                         if (efa->tmp.l) {
1794                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1795                                 if (select) {
1796                                         simaFaceSel_Set(efa, tf);
1797                                 } else {
1798                                         simaFaceSel_UnSet(efa, tf);
1799                                 }
1800                         }
1801                 }
1802         }
1803 }
1804
1805 void pin_tface_uv(int mode)
1806 {
1807         EditMesh *em = G.editMesh;
1808         EditFace *efa;
1809         MTFace *tface;
1810         
1811         if( is_uv_tface_editing_allowed()==0 ) return;
1812         
1813         for (efa= em->faces.first; efa; efa= efa->next) {
1814                 tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1815                 if (simaFaceDraw_Check(efa, tface)) {
1816                         if(mode ==1) {
1817                                 if(simaUVSel_Check(efa, tface, 0)) tface->unwrap |= TF_PIN1;
1818                                 if(simaUVSel_Check(efa, tface, 1)) tface->unwrap |= TF_PIN2;
1819                                 if(simaUVSel_Check(efa, tface, 2)) tface->unwrap |= TF_PIN3;
1820                                 if(efa->v4)
1821                                         if(simaUVSel_Check(efa, tface, 3)) tface->unwrap |= TF_PIN4;
1822                         }
1823                         else if (mode ==0) {
1824                                 if(simaUVSel_Check(efa, tface, 0)) tface->unwrap &= ~TF_PIN1;
1825                                 if(simaUVSel_Check(efa, tface, 1)) tface->unwrap &= ~TF_PIN2;
1826                                 if(simaUVSel_Check(efa, tface, 2)) tface->unwrap &= ~TF_PIN3;
1827                                 if(efa->v4)
1828                                         if(simaUVSel_Check(efa, tface, 3)) tface->unwrap &= ~TF_PIN4;
1829                         }
1830                 }
1831         }
1832         
1833         BIF_undo_push("Pin UV");
1834         scrarea_queue_winredraw(curarea);
1835 }
1836
1837 void select_pinned_tface_uv(void)
1838 {
1839         EditMesh *em= G.editMesh;
1840         EditFace *efa;
1841         MTFace *tface;
1842         
1843         if( is_uv_tface_editing_allowed()==0 ) return;
1844         
1845         for (efa= em->faces.first; efa; efa= efa->next) {
1846                 tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1847                 if (simaFaceDraw_Check(efa, tface)) {
1848                         if (tface->unwrap & TF_PIN1) simaUVSel_Set(efa, tface, 0);
1849                         if (tface->unwrap & TF_PIN2) simaUVSel_Set(efa, tface, 1);
1850                         if (tface->unwrap & TF_PIN3) simaUVSel_Set(efa, tface, 2);
1851                         if(efa->v4) {
1852                                 if (tface->unwrap & TF_PIN4) simaUVSel_Set(efa, tface, 3);
1853                         }
1854                         
1855                 }
1856         }
1857         
1858         if (G.sima->flag & SI_SYNC_UVSEL) {
1859                 allqueue(REDRAWVIEW3D, 0); /* mesh selection has changed */
1860         }
1861         
1862         BIF_undo_push("Select Pinned UVs");
1863         scrarea_queue_winredraw(curarea);
1864 }
1865
1866 /* UV edge loop select, follows same rules as editmesh */
1867
1868 static void uv_vertex_loop_flag(UvMapVert *first)
1869 {
1870         UvMapVert *iterv;
1871         int count= 0;
1872
1873         for(iterv=first; iterv; iterv=iterv->next) {
1874                 if(iterv->separate && iterv!=first)
1875                         break;
1876
1877                 count++;
1878         }
1879         
1880         if(count < 5)
1881                 first->flag= 1;
1882 }
1883
1884 static UvMapVert *uv_vertex_map_get(UvVertMap *vmap, EditFace *efa, int a)
1885 {
1886         UvMapVert *iterv, *first;
1887         
1888         first= get_uv_map_vert_EM(vmap, (*(&efa->v1 + a))->tmp.l);
1889
1890         for(iterv=first; iterv; iterv=iterv->next) {
1891                 if(iterv->separate)
1892                         first= iterv;
1893                 if(iterv->f == efa->tmp.l)
1894                         return first;
1895         }
1896         
1897         return NULL;
1898 }
1899
1900 static int uv_edge_tag_faces(UvMapVert *first1, UvMapVert *first2, int *totface)
1901 {
1902         UvMapVert *iterv1, *iterv2;
1903         EditFace *efa;
1904         int tot = 0;
1905
1906         /* count number of faces this edge has */
1907         for(iterv1=first1; iterv1; iterv1=iterv1->next) {
1908                 if(iterv1->separate && iterv1 != first1)
1909                         break;
1910
1911                 for(iterv2=first2; iterv2; iterv2=iterv2->next) {
1912                         if(iterv2->separate && iterv2 != first2)
1913                                 break;
1914
1915                         if(iterv1->f == iterv2->f) {
1916                                 /* if face already tagged, don't do this edge */
1917                                 efa= EM_get_face_for_index(iterv1->f);
1918                                 if(efa->f1)
1919                                         return 0;
1920
1921                                 tot++;
1922                                 break;
1923                         }
1924                 }
1925         }
1926
1927         if(*totface == 0) /* start edge */
1928                 *totface= tot;
1929         else if(tot != *totface) /* check for same number of faces as start edge */
1930                 return 0;
1931
1932         /* tag the faces */
1933         for(iterv1=first1; iterv1; iterv1=iterv1->next) {
1934                 if(iterv1->separate && iterv1 != first1)
1935                         break;
1936
1937                 for(iterv2=first2; iterv2; iterv2=iterv2->next) {
1938                         if(iterv2->separate && iterv2 != first2)
1939                                 break;
1940
1941                         if(iterv1->f == iterv2->f) {
1942                                 efa= EM_get_face_for_index(iterv1->f);
1943                                 efa->f1= 1;
1944                                 break;
1945                         }
1946                 }
1947         }
1948
1949         return 1;
1950 }
1951
1952 void select_edgeloop_tface_uv(EditFace *startefa, int starta, int shift, int *flush)
1953 {
1954         EditMesh *em= G.editMesh;
1955         EditVert *eve;
1956         EditFace *efa;
1957         MTFace *tface;
1958         UvVertMap *vmap;
1959         UvMapVert *iterv1, *iterv2;
1960         float limit[2];
1961         int a, count, looking, nverts, starttotface, select;
1962         
1963         if( is_uv_tface_editing_allowed()==0 ) return;
1964
1965         /* setup */
1966         EM_init_index_arrays(0, 0, 1);
1967
1968         get_connected_limit_tface_uv(limit);
1969         vmap= make_uv_vert_map_EM(0, 0, limit);
1970
1971         for(count=0, eve=em->verts.first; eve; count++, eve= eve->next)
1972                 eve->tmp.l = count;
1973
1974         for(count=0, efa= em->faces.first; efa; count++, efa= efa->next) {
1975                 if(!shift) {
1976                         tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1977                         simaFaceSel_UnSet(efa, tface);
1978                 }
1979
1980                 efa->tmp.l= count;
1981                 efa->f1= 0;
1982         }
1983         
1984         /* set flags for first face and verts */
1985         nverts= (startefa->v4)? 4: 3;
1986         iterv1= uv_vertex_map_get(vmap, startefa, starta);
1987         iterv2= uv_vertex_map_get(vmap, startefa, (starta+1)%nverts);
1988         uv_vertex_loop_flag(iterv1);
1989         uv_vertex_loop_flag(iterv2);
1990
1991         starttotface= 0;
1992         uv_edge_tag_faces(iterv1, iterv2, &starttotface);
1993
1994         /* sorry, first edge isnt even ok */
1995         if(iterv1->flag==0 && iterv2->flag==0) looking= 0;
1996         else looking= 1;
1997
1998         /* iterate */
1999         while(looking) {
2000                 looking= 0;
2001
2002                 /* find correct valence edges which are not tagged yet, but connect to tagged one */
2003                 for(efa= em->faces.first; efa; efa=efa->next) {
2004                         tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2005
2006                         if(!efa->f1 && simaFaceDraw_Check(efa, tface)) {
2007                                 nverts= (efa->v4)? 4: 3;
2008                                 for(a=0; a<nverts; a++) {
2009                                         /* check face not hidden and not tagged */
2010                                         iterv1= uv_vertex_map_get(vmap, efa, a);
2011                                         iterv2= uv_vertex_map_get(vmap, efa, (a+1)%nverts);
2012
2013                                         /* check if vertex is tagged and has right valence */
2014                                         if(iterv1->flag || iterv2->flag) {
2015                                                 if(uv_edge_tag_faces(iterv1, iterv2, &starttotface)) {
2016                                                         looking= 1;
2017                                                         efa->f1= 1;
2018
2019                                                         uv_vertex_loop_flag(iterv1);
2020                                                         uv_vertex_loop_flag(iterv2);
2021                                                         break;
2022                                                 }
2023                                         }
2024                                 }
2025                         }
2026                 }
2027         }
2028
2029         /* do the actual select/deselect */
2030         nverts= (startefa->v4)? 4: 3;
2031         iterv1= uv_vertex_map_get(vmap, startefa, starta);
2032         iterv2= uv_vertex_map_get(vmap, startefa, (starta+1)%nverts);
2033         iterv1->flag= 1;
2034         iterv2->flag= 1;
2035
2036         if(shift) {
2037                 tface= CustomData_em_get(&em->fdata, startefa->data, CD_MTFACE);
2038                 if(simaUVSel_Check(startefa, tface, starta) && simaUVSel_Check(startefa, tface, starta))
2039                         select= 0;
2040                 else
2041                         select= 1;
2042         }
2043         else
2044                 select= 1;
2045         
2046         if(select) *flush= 1;
2047         else *flush= -1;
2048
2049         for(efa= em->faces.first; efa; efa=efa->next) {
2050                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2051
2052                 nverts= (efa->v4)? 4: 3;
2053                 for(a=0; a<nverts; a++) {
2054                         iterv1= uv_vertex_map_get(vmap, efa, a);
2055
2056                         if(iterv1->flag) {
2057                                 if(select) simaUVSel_Set(efa, tface, a);
2058                                 else simaUVSel_UnSet(efa, tface, a);
2059                         }
2060                 }
2061         }
2062
2063         /* cleanup */
2064         free_uv_vert_map_EM(vmap);
2065         EM_free_index_arrays();
2066 }
2067
2068 int minmax_tface_uv(float *min, float *max)
2069 {
2070         EditMesh *em= G.editMesh;
2071         EditFace *efa;
2072         MTFace *tf;
2073         int sel;
2074         
2075         if( is_uv_tface_editing_allowed()==0 ) return 0;
2076
2077         INIT_MINMAX2(min, max);
2078
2079         sel= 0;
2080         for (efa= em->faces.first; efa; efa= efa->next) {
2081                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2082                 if (simaFaceDraw_Check(efa, tf)) {
2083                         if (simaUVSel_Check(efa, tf, 0))                                { DO_MINMAX2(tf->uv[0], min, max); sel = 1; }
2084                         if (simaUVSel_Check(efa, tf, 1))                                { DO_MINMAX2(tf->uv[1], min, max); sel = 1; }
2085                         if (simaUVSel_Check(efa, tf, 2))                                { DO_MINMAX2(tf->uv[2], min, max); sel = 1; }
2086                         if (efa->v4 && (simaUVSel_Check(efa, tf, 3)))   { DO_MINMAX2(tf->uv[3], min, max); sel = 1; }
2087                 }
2088         }
2089         return sel;
2090 }
2091
2092 int cent_tface_uv(float *cent, int mode)
2093 {
2094         float min[2], max[2];
2095         short change= 0;
2096         
2097         if (mode==0) {
2098                 if (minmax_tface_uv(min, max))
2099                         change = 1;
2100
2101         } else if (mode==1) {
2102                 EditFace *efa;
2103                 MTFace *tf;
2104                 INIT_MINMAX2(min, max);
2105                 
2106                 for (efa= G.editMesh->faces.first; efa; efa= efa->next) {
2107                         tf = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
2108                         if (simaFaceDraw_Check(efa, tf)) {
2109                                 if (simaUVSel_Check(efa, tf, 0))                                { DO_MINMAX2(tf->uv[0], min, max);      change= 1;}
2110                                 if (simaUVSel_Check(efa, tf, 1))                                { DO_MINMAX2(tf->uv[1], min, max);      change= 1;}
2111                                 if (simaUVSel_Check(efa, tf, 2))                                { DO_MINMAX2(tf->uv[2], min, max);      change= 1;}
2112                                 if (efa->v4 && (simaUVSel_Check(efa, tf, 3)))   { DO_MINMAX2(tf->uv[3], min, max);      change= 1;}
2113                         }
2114                 }
2115         }
2116         
2117         if (change) {
2118                 cent[0]= (min[0]+max[0])/2.0;
2119                 cent[1]= (min[1]+max[1])/2.0;
2120                 return 1;
2121         }
2122         return 0;
2123 }
2124
2125 static void sima_show_info(int channels, int x, int y, char *cp, float *fp, int *zp, float *zpf)
2126 {
2127         short ofs;
2128         char str[256];
2129         
2130         ofs= sprintf(str, "X: %d Y: %d ", x, y);
2131         if(cp)
2132                 ofs+= sprintf(str+ofs, "| R: %d G: %d B: %d A: %d ", cp[0], cp[1], cp[2], cp[3]);
2133         if(fp) {
2134                 if(channels==4)
2135                         ofs+= sprintf(str+ofs, "| R: %.3f G: %.3f B: %.3f A: %.3f ", fp[0], fp[1], fp[2], fp[3]);
2136                 else if(channels==1)
2137                         ofs+= sprintf(str+ofs, "| Val: %.3f ", fp[0]);
2138                 else if(channels==3)
2139                         ofs+= sprintf(str+ofs, "| R: %.3f G: %.3f B: %.3f ", fp[0], fp[1], fp[2]);
2140         }
2141         if(zp)
2142                 ofs+= sprintf(str+ofs, "| Z: %.4f ", 0.5+0.5*( ((float)*zp)/(float)0x7fffffff));
2143         if(zpf)
2144                 ofs+= sprintf(str+ofs, "| Z: %.3f ", *zpf);
2145         
2146         glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
2147         glEnable(GL_BLEND);
2148         
2149         glColor4f(.0,.0,.0,.25);
2150         glRectf(0.0, 0.0, curarea->winx, 30.0);
2151         glDisable(GL_BLEND);
2152         
2153         glColor3ub(255, 255, 255);
2154         glRasterPos2i(10, 10);
2155         
2156         BMF_DrawString(G.fonts, str);
2157
2158 }
2159
2160 void sima_sample_color(void)
2161 {
2162         ImBuf *ibuf= imagewindow_get_ibuf(G.sima);
2163         float fx, fy;
2164         short mval[2], mvalo[2], firsttime=1;
2165         
2166         if(ibuf==NULL)
2167                 return;
2168         
2169         calc_image_view(G.sima, 'f');
2170         getmouseco_areawin(mvalo);
2171         
2172         while(get_mbut() & L_MOUSE) {
2173                 
2174                 getmouseco_areawin(mval);
2175                 if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || firsttime) {
2176                         firsttime= 0;
2177                         areamouseco_to_ipoco(G.v2d, mval, &fx, &fy);
2178                         
2179                         if(fx>=0.0 && fy>=0.0 && fx<1.0 && fy<1.0) {
2180                                 float *fp= NULL, *zpf= NULL;
2181                                 float vec[3];
2182                                 int *zp= NULL;
2183                                 char *cp= NULL;
2184                                 
2185                                 int x= (int) (fx*ibuf->x);
2186                                 int y= (int) (fy*ibuf->y);
2187                                 
2188                                 if(x>=ibuf->x) x= ibuf->x-1;
2189                                 if(y>=ibuf->y) y= ibuf->y-1;
2190                                 
2191                                 if(ibuf->rect)
2192                                         cp= (char *)(ibuf->rect + y*ibuf->x + x);
2193                                 if(ibuf->zbuf)
2194                                         zp= ibuf->zbuf + y*ibuf->x + x;
2195                                 if(ibuf->zbuf_float)
2196                                         zpf= ibuf->zbuf_float + y*ibuf->x + x;
2197                                 if(ibuf->rect_float)
2198                                         fp= (ibuf->rect_float + (ibuf->channels)*(y*ibuf->x + x));
2199                                         
2200                                 if(fp==NULL) {
2201                                         fp= vec;
2202                                         vec[0]= (float)cp[0]/255.0f;
2203                                         vec[1]= (float)cp[1]/255.0f;
2204                                         vec[2]= (float)cp[2]/255.0f;
2205                                 }
2206                                 
2207                                 if(G.sima->cumap) {
2208                                         
2209                                         if(ibuf->channels==4) {
2210                                                 if(G.qual & LR_CTRLKEY) {
2211                                                         curvemapping_set_black_white(G.sima->cumap, NULL, fp);
2212                                                         curvemapping_do_ibuf(G.sima->cumap, ibuf);
2213                                                 }
2214                                                 else if(G.qual & LR_SHIFTKEY) {
2215                                                         curvemapping_set_black_white(G.sima->cumap, fp, NULL);
2216                                                         curvemapping_do_ibuf(G.sima->cumap, ibuf);
2217                                                 }
2218                                         }
2219                                 }
2220                                 
2221                                 {
2222                                         ScrArea *sa, *cur= curarea;
2223                                         
2224                                         node_curvemap_sample(fp);       /* sends global to node editor */
2225                                         for(sa= G.curscreen->areabase.first; sa; sa= sa->next) {
2226                                                 if(sa->spacetype==SPACE_NODE) {
2227                                                         areawinset(sa->win);
2228                                                         scrarea_do_windraw(sa);
2229                                                 }
2230                                         }
2231                                         node_curvemap_sample(NULL);             /* clears global in node editor */
2232                                         curarea= cur;
2233                                 }
2234                                 
2235                                 areawinset(curarea->win);
2236                                 scrarea_do_windraw(curarea);
2237                                 myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
2238                                 glLoadIdentity();
2239                                 
2240                                 sima_show_info(ibuf->channels, x, y, cp, (ibuf->rect_float)?fp:NULL, zp, zpf);
2241                                 
2242                                 screen_swapbuffers();
2243                                 
2244                         }
2245                 }
2246                 BIF_wait_for_statechange();
2247         }
2248         
2249         scrarea_queue_winredraw(curarea);
2250         
2251 }
2252
2253 /* Image functions */
2254
2255 static void load_image_filesel(char *str)       /* called from fileselect */
2256 {
2257         Image *ima= NULL;
2258
2259         ima= BKE_add_image_file(str);
2260         if(ima) {
2261                 BKE_image_signal(ima, &G.sima->iuser, IMA_SIGNAL_RELOAD);
2262                 image_changed(G.sima, ima);
2263         }
2264         BIF_undo_push("Load image UV");
2265         allqueue(REDRAWIMAGE, 0);
2266 }
2267
2268 static void replace_image_filesel(char *str)            /* called from fileselect */
2269 {
2270         if (!G.sima->image)
2271                 return;
2272         
2273         strncpy(G.sima->image->name, str, sizeof(G.sima->image->name)-1); /* we cant do much if the str is longer then 240 :/ */
2274         BKE_image_signal(G.sima->image, &G.sima->iuser, IMA_SIGNAL_RELOAD);
2275         BIF_undo_push("Replace image UV");
2276         allqueue(REDRAWIMAGE, 0);
2277         allqueue(REDRAWVIEW3D, 0);
2278 }
2279
2280
2281 static void save_image_doit(char *name)
2282 {
2283         Image *ima= G.sima->image;
2284         ImBuf *ibuf= imagewindow_get_ibuf(G.sima);
2285         int len;
2286         char str[FILE_MAXDIR+FILE_MAXFILE];
2287
2288         if (ibuf) {
2289                 BLI_strncpy(str, name, sizeof(str));
2290
2291                 BLI_convertstringcode(str, G.sce);
2292                 BLI_convertstringframe(str, G.scene->r.cfra);
2293                 
2294                 
2295                 if(G.scene->r.scemode & R_EXTENSION)  {
2296                         BKE_add_image_extension(str, G.sima->imtypenr);
2297                         BKE_add_image_extension(name, G.sima->imtypenr);
2298                 }
2299                 
2300                 if (saveover(str)) {
2301                         
2302                         /* enforce user setting for RGB or RGBA, but skip BW */
2303                         if(G.scene->r.planes==32)
2304                                 ibuf->depth= 32;
2305                         else if(G.scene->r.planes==24)
2306                                 ibuf->depth= 24;
2307                         
2308                         waitcursor(1);
2309                         if(G.sima->imtypenr==R_MULTILAYER) {
2310                                 RenderResult *rr= BKE_image_get_renderresult(ima);
2311                                 if(rr) {
2312                                         RE_WriteRenderResult(rr, str, G.scene->r.quality);
2313                                         
2314                                         BLI_strncpy(ima->name, name, sizeof(ima->name));
2315                                         BLI_strncpy(ibuf->name, str, sizeof(ibuf->name));
2316                                         
2317                                         /* should be function? nevertheless, saving only happens here */
2318                                         for(ibuf= ima->ibufs.first; ibuf; ibuf= ibuf->next)
2319                                                 ibuf->userflags &= ~IB_BITMAPDIRTY;
2320                                         
2321                                 }
2322                                 else error("Did not write, no Multilayer Image");
2323                         }
2324                         else if (BKE_write_ibuf(ibuf, str, G.sima->imtypenr, G.scene->r.subimtype, G.scene->r.quality)) {
2325                                 BLI_strncpy(ima->name, name, sizeof(ima->name));
2326                                 BLI_strncpy(ibuf->name, str, sizeof(ibuf->name));
2327                                 
2328                                 ibuf->userflags &= ~IB_BITMAPDIRTY;
2329                                 
2330                                 /* change type? */
2331                                 if( ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC_VIEWER)) {
2332                                         ima->source= IMA_SRC_FILE;
2333                                         ima->type= IMA_TYPE_IMAGE;
2334                                 }
2335                                 if(ima->type==IMA_TYPE_R_RESULT)
2336                                         ima->type= IMA_TYPE_IMAGE;
2337                                 
2338                                 /* name image as how we saved it */
2339                                 len= strlen(str);
2340                                 while (len > 0 && str[len - 1] != '/' && str[len - 1] != '\\') len--;
2341                                 rename_id(&ima->id, str+len);
2342                         } 
2343                         else {
2344                                 error("Couldn't write image: %s", str);
2345                         }
2346
2347                         allqueue(REDRAWHEADERS, 0);
2348                         allqueue(REDRAWBUTSSHADING, 0);
2349
2350                         waitcursor(0);
2351                 }
2352         }
2353 }
2354
2355 void open_image_sima(short imageselect)
2356 {
2357         char name[FILE_MAXDIR+FILE_MAXFILE];
2358
2359         if(G.sima->image)
2360                 strcpy(name, G.sima->image->name);
2361         else
2362                 strcpy(name, U.textudir);
2363
2364         if(imageselect)
2365                 activate_imageselect(FILE_SPECIAL, "Open Image", name, load_image_filesel);
2366         else
2367                 activate_fileselect(FILE_SPECIAL, "Open Image", name, load_image_filesel);
2368 }
2369
2370 void replace_image_sima(short imageselect)
2371 {
2372         char name[FILE_MAXDIR+FILE_MAXFILE];
2373
2374         if(G.sima->image)
2375                 strcpy(name, G.sima->image->name);
2376         else
2377                 strcpy(name, U.textudir);
2378         
2379         if(imageselect)
2380                 activate_imageselect(FILE_SPECIAL, "Replace Image", name, replace_image_filesel);
2381         else
2382                 activate_fileselect(FILE_SPECIAL, "Replace Image", name, replace_image_filesel);
2383 }
2384
2385
2386 static char *filesel_imagetype_string(Image *ima)
2387 {
2388         char *strp, *str= MEM_callocN(14*32, "menu for filesel");
2389         
2390         strp= str;
2391         str += sprintf(str, "Save Image as: %%t|");
2392         str += sprintf(str, "Targa %%x%d|", R_TARGA);
2393         str += sprintf(str, "Targa Raw %%x%d|", R_RAWTGA);
2394         str += sprintf(str, "PNG %%x%d|", R_PNG);
2395         str += sprintf(str, "BMP %%x%d|", R_BMP);
2396         str += sprintf(str, "Jpeg %%x%d|", R_JPEG90);
2397         str += sprintf(str, "Iris %%x%d|", R_IRIS);
2398         if(G.have_libtiff)
2399                 str += sprintf(str, "Tiff %%x%d|", R_TIFF);
2400         str += sprintf(str, "Radiance HDR %%x%d|", R_RADHDR);
2401         str += sprintf(str, "Cineon %%x%d|", R_CINEON);
2402         str += sprintf(str, "DPX %%x%d|", R_DPX);
2403 #ifdef WITH_OPENEXR
2404         str += sprintf(str, "OpenEXR %%x%d|", R_OPENEXR);
2405         /* saving sequences of multilayer won't work, they copy buffers  */
2406         if(ima->source==IMA_SRC_SEQUENCE && ima->type==IMA_TYPE_MULTILAYER);
2407         else str += sprintf(str, "MultiLayer %%x%d|", R_MULTILAYER);
2408 #endif  
2409         return strp;
2410 }
2411
2412 /* always opens fileselect */
2413 void save_as_image_sima(void)
2414 {
2415         Image *ima = G.sima->image;
2416         ImBuf *ibuf= imagewindow_get_ibuf(G.sima);
2417         char name[FILE_MAXDIR+FILE_MAXFILE];
2418
2419         if (ima) {
2420                 strcpy(name, ima->name);
2421
2422                 if (ibuf) {
2423                         char *strp;
2424                         
2425                         strp= filesel_imagetype_string(ima);
2426                         
2427                         /* cant save multilayer sequence, ima->rr isn't valid for a specific frame */
2428                         if(ima->rr && !(ima->source==IMA_SRC_SEQUENCE && ima->type==IMA_TYPE_MULTILAYER))
2429                                 G.sima->imtypenr= R_MULTILAYER;
2430                         else if(ima->type==IMA_TYPE_R_RESULT)
2431                                 G.sima->imtypenr= G.scene->r.imtype;
2432                         else G.sima->imtypenr= BKE_ftype_to_imtype(ibuf->ftype);
2433                         
2434                         activate_fileselect_menu(FILE_SPECIAL, "Save Image", name, strp, &G.sima->imtypenr, save_image_doit);
2435                 }
2436         }
2437 }
2438
2439 /* if exists, saves over without fileselect */
2440 void save_image_sima(void)
2441 {
2442         Image *ima = G.sima->image;
2443         ImBuf *ibuf= imagewindow_get_ibuf(G.sima);
2444         char name[FILE_MAXDIR+FILE_MAXFILE];
2445
2446         if (ima) {
2447                 strcpy(name, ima->name);
2448
2449                 if (ibuf) {
2450                         if (BLI_exists(ibuf->name)) {
2451                                 if(BKE_image_get_renderresult(ima)) 
2452                                         G.sima->imtypenr= R_MULTILAYER;
2453                                 else 
2454                                         G.sima->imtypenr= BKE_ftype_to_imtype(ibuf->ftype);
2455                                 
2456                                 save_image_doit(ibuf->name);
2457                         }
2458                         else
2459                                 save_as_image_sima();
2460                 }
2461         }
2462 }
2463
2464 void save_image_sequence_sima(void)
2465 {
2466         ImBuf *ibuf;
2467         int tot= 0;
2468         char di[FILE_MAX], fi[FILE_MAX];
2469         
2470         if(G.sima->image==NULL)
2471                 return;
2472         if(G.sima->image->source!=IMA_SRC_SEQUENCE)
2473                 return;
2474         if(G.sima->image->type==IMA_TYPE_MULTILAYER) {
2475                 error("Cannot save Multilayer Sequences");
2476                 return;
2477         }
2478         
2479         /* get total */
2480         for(ibuf= G.sima->image->ibufs.first; ibuf; ibuf= ibuf->next) 
2481                 if(ibuf->userflags & IB_BITMAPDIRTY)
2482                         tot++;
2483         
2484         if(tot==0) {
2485                 notice("No Images have been changed");
2486                 return;
2487         }
2488         /* get a filename for menu */
2489         for(ibuf= G.sima->image->ibufs.first; ibuf; ibuf= ibuf->next) 
2490                 if(ibuf->userflags & IB_BITMAPDIRTY)
2491                         break;
2492         
2493         BLI_strncpy(di, ibuf->name, FILE_MAX);
2494         BLI_splitdirstring(di, fi);
2495         
2496         sprintf(fi, "%d Image(s) will be saved in %s", tot, di);
2497         if(okee(fi)) {
2498                 
2499                 for(ibuf= G.sima->image->ibufs.first; ibuf; ibuf= ibuf->next) {
2500                         if(ibuf->userflags & IB_BITMAPDIRTY) {
2501                                 char name[FILE_MAX];
2502                                 BLI_strncpy(name, ibuf->name, sizeof(name));
2503                                 
2504                                 BLI_convertstringcode(name, G.sce);
2505
2506                                 if(0 == IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat)) {
2507                                         error("Could not write image", name);
2508                                         break;
2509                                 }
2510                                 printf("Saved: %s\n", ibuf->name);
2511                                 ibuf->userflags &= ~IB_BITMAPDIRTY;
2512                         }
2513                 }
2514         }
2515 }
2516
2517 void reload_image_sima(void)
2518 {
2519         if (G.sima ) {
2520                 BKE_image_signal(G.sima->image, &G.sima->iuser, IMA_SIGNAL_RELOAD);
2521                 /* image_changed(G.sima, 0); - do we really need this? */
2522         }
2523
2524         allqueue(REDRAWIMAGE, 0);
2525         allqueue(REDRAWVIEW3D, 0);
2526         BIF_preview_changed(ID_TE);
2527 }
2528
2529 void new_image_sima(void)
2530 {
2531         static int width= 1024, height= 1024;
2532         static short uvtestgrid= 0;
2533         static int floatbuf=0;
2534         static float color[] = {0, 0, 0, 1};
2535         char name[22];
2536         Image *ima;
2537         
2538         strcpy(name, "Untitled");
2539
2540         add_numbut(0, TEX, "Name:", 0, 21, name, NULL);
2541         add_numbut(1, NUM|INT, "Width:", 1, 16384, &width, NULL);
2542         add_numbut(2, NUM|INT, "Height:", 1, 16384, &height, NULL);
2543         add_numbut(3, COL, "", 0, 0, &color, NULL);
2544         add_numbut(4, NUM|FLO, "Alpha:", 0.0, 1.0, &color[3], NULL);
2545         add_numbut(5, TOG|SHO, "UV Test Grid", 0, 0, &uvtestgrid, NULL);
2546         add_numbut(6, TOG|INT, "32 bit Float", 0, 0, &floatbuf, NULL);
2547         if (!do_clever_numbuts("New Image", 7, REDRAW))
2548                 return;
2549
2550         ima = BKE_add_image_size(width, height, name, floatbuf, uvtestgrid, color);
2551         image_changed(G.sima, ima);
2552         BKE_image_signal(G.sima->image, &G.sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE);
2553         BIF_undo_push("Add image");
2554
2555         allqueue(REDRAWIMAGE, 0);
2556         allqueue(REDRAWVIEW3D, 0);
2557 }
2558
2559 void pack_image_sima()
2560 {
2561         Image *ima = G.sima->image;
2562
2563         if (ima) {
2564                 if(ima->source!=IMA_SRC_SEQUENCE && ima->source!=IMA_SRC_MOVIE) {
2565                         if (ima->packedfile) {
2566                                 if (G.fileflags & G_AUTOPACK)
2567                                         if (okee("Disable AutoPack?"))
2568                                                 G.fileflags &= ~G_AUTOPACK;
2569                                 
2570                                 if ((G.fileflags & G_AUTOPACK) == 0) {
2571                                         unpackImage(ima, PF_ASK);
2572                                         BIF_undo_push("Unpack image");
2573                                 }
2574                         }
2575                         else {
2576                                 ImBuf *ibuf= imagewindow_get_ibuf(G.sima);
2577                                 if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) {
2578                                         if(okee("Can't pack painted image. Use Repack as PNG?"))
2579                                                 BKE_image_memorypack(ima);
2580                                 }
2581                                 else {
2582                                         ima->packedfile = newPackedFile(ima->name);
2583                                         BIF_undo_push("Pack image");
2584                                 }
2585                         }
2586
2587                         allqueue(REDRAWBUTSSHADING, 0);
2588                         allqueue(REDRAWHEADERS, 0);
2589                 }
2590         }
2591 }
2592
2593
2594
2595 /* goes over all ImageUsers, and sets frame numbers if auto-refresh is set */
2596 void BIF_image_update_frame(void)
2597 {
2598         Tex *tex;
2599         
2600         /* texture users */
2601         for(tex= G.main->tex.first; tex; tex= tex->id.next) {
2602                 if(tex->type==TEX_IMAGE && tex->ima)
2603                         if(ELEM(tex->ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE))
2604                                 if(tex->iuser.flag & IMA_ANIM_ALWAYS)
2605                                         BKE_image_user_calc_imanr(&tex->iuser, G.scene->r.cfra, 0);
2606                 
2607         }
2608         /* image window, compo node users */
2609         if(G.curscreen) {
2610                 ScrArea *sa;
2611                 for(sa= G.curscreen->areabase.first; sa; sa= sa->next) {
2612                         if(sa->spacetype==SPACE_VIEW3D) {
2613                                 View3D *v3d= sa->spacedata.first;
2614                                 if(v3d->bgpic)
2615                                         if(v3d->bgpic->iuser.flag & IMA_ANIM_ALWAYS)
2616                                                 BKE_image_user_calc_imanr(&v3d->bgpic->iuser, G.scene->r.cfra, 0);
2617                         }
2618                         else if(sa->spacetype==SPACE_IMAGE) {
2619                                 SpaceImage *sima= sa->spacedata.first;
2620                                 if(sima->iuser.flag & IMA_ANIM_ALWAYS)
2621                                         BKE_image_user_calc_imanr(&sima->iuser, G.scene->r.cfra, 0);
2622                         }
2623                         else if(sa->spacetype==SPACE_NODE) {
2624                                 SpaceNode *snode= sa->spacedata.first;
2625                                 if((snode->treetype==NTREE_COMPOSIT) && (snode->nodetree)) {
2626                                         bNode *node;
2627                                         for(node= snode->nodetree->nodes.first; node; node= node->next) {
2628                                                 if(node->id && node->type==CMP_NODE_IMAGE) {
2629                                                         Image *ima= (Image *)node->id;
2630                                                         ImageUser *iuser= node->storage;
2631                                                         if(ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE))
2632                                                                 if(iuser->flag & IMA_ANIM_ALWAYS)
2633                                                                         BKE_image_user_calc_imanr(iuser, G.scene->r.cfra, 0);
2634                                                 }
2635                                         }
2636                                 }
2637                         }
2638                 }
2639         }
2640 }
2641
2642 extern int EM_texFaceCheck(void); /* from editmesh.c */
2643 /* called to assign images to UV faces */
2644 void image_changed(SpaceImage *sima, Image *image)
2645 {
2646         MTFace *tface;
2647         EditMesh *em = G.editMesh;
2648         EditFace *efa;
2649         ImBuf *ibuf = NULL;
2650         short change = 0;
2651         
2652         if(image==NULL) {
2653                 sima->flag &= ~SI_DRAWTOOL;
2654         } else {
2655                 ibuf = BKE_image_get_ibuf(image, NULL);
2656         }
2657         
2658         if(sima->mode!=SI_TEXTURE)
2659                 return;
2660         
2661         /* skip assigning these procedural images... */
2662         if(image && (image->type==IMA_TYPE_R_RESULT || image->type==IMA_TYPE_COMPOSITE)) {
2663                 return;
2664         } else if ((G.obedit) &&
2665                         (G.obedit->type == OB_MESH) &&
2666                         (G.editMesh) &&
2667                         (G.editMesh->faces.first)
2668                 ) {
2669                 
2670                 /* Add a UV layer if there is none, editmode only */
2671                 if ( !CustomData_has_layer(&G.editMesh->fdata, CD_MTFACE) ) {
2672                         EM_add_data_layer(&em->fdata, CD_MTFACE);
2673                         CustomData_set_layer_active(&em->fdata, CD_MTFACE, 0); /* always zero because we have no other UV layers */
2674                         change = 1; /* so we update the object, incase no faces are selected */
2675                         
2676                         /* BIF_undo_push("New UV Texture"); - undo should be done by whatever changes the image */
2677                         allqueue(REDRAWVIEW3D, 0);
2678                         allqueue(REDRAWBUTSEDIT, 0);
2679                 }
2680                 
2681                 for (efa= em->faces.first; efa; efa= efa->next) {
2682                         tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2683                         if (efa->h==0 && efa->f & SELECT) {
2684                                 if (image) {
2685                                         tface->tpage= image;
2686                                         tface->mode |= TF_TEX;
2687                                         
2688                                         if(image->tpageflag & IMA_TILES) tface->mode |= TF_TILES;
2689                                         else tface->mode &= ~TF_TILES;
2690                                         
2691                                         if(image->id.us==0) id_us_plus(&image->id);
2692                                         else id_lib_extern(&image->id);
2693                                         
2694                                         if (tface->transp==TF_ADD) {} /* they obviously know what they are doing! - leave as is */
2695                                         else if (ibuf && ibuf->depth == 32)     tface->transp = TF_ALPHA;
2696                                         else                                                            tface->transp = TF_SOLID;
2697                                         
2698                                 } else {
2699                                         tface->tpage= NULL;
2700                                         tface->mode &= ~TF_TEX;
2701                                         tface->transp = TF_SOLID;
2702                                 }
2703                                 change = 1;
2704                         }
2705                 }
2706         }
2707         /* change the space image after because simaFaceDraw_Check uses the space image
2708          * to check if the face is displayed in UV-localview */
2709         sima->image = image;
2710         
2711         if (change)
2712                 object_uvs_changed(OBACT);
2713         
2714         allqueue(REDRAWBUTSEDIT, 0);
2715 }
2716
2717 void image_pixel_aspect(Image *image, float *x, float *y)
2718 {
2719         *x = *y = 1.0;
2720         
2721         if(             (image == NULL) ||
2722                         (image->type == IMA_TYPE_R_RESULT) ||
2723                         (image->type == IMA_TYPE_COMPOSITE) ||
2724                         (image->tpageflag & IMA_TILES) ||
2725                         (image->aspx==0.0 || image->aspy==0.0)
2726         ) {
2727                 return;
2728         }
2729         
2730         /* x is always 1 */
2731         *y = image->aspy / image->aspx;
2732 }
2733
2734 void image_final_aspect(Image *image, float *x, float *y)
2735 {
2736         *x = *y = 1.0;
2737         
2738         if(             (image == NULL) ||
2739                         (image->type == IMA_TYPE_R_RESULT) ||
2740                         (image->type == IMA_TYPE_COMPOSITE) ||
2741                         (image->tpageflag & IMA_TILES) ||
2742                         (image->aspx==0.0 || image->aspy==0.0)
2743         ) {
2744                 return;
2745         } else {
2746                 ImBuf *ibuf= BKE_image_get_ibuf(image, NULL);
2747                 if (ibuf && ibuf->x && ibuf->y)  {
2748                         *y = (image->aspy * ibuf->y) / (image->aspx * ibuf->x);
2749                 } else {
2750                         /* x is always 1 */
2751                         *y = image->aspy / image->aspx;
2752                 }
2753         }
2754 }
2755
2756 /* Face selection tests  - Keep these together */
2757
2758 /* this checks weather a face is drarn without the local image check */
2759 int simaFaceDraw_Check_nolocal( EditFace *efa )
2760 {
2761         if (G.sima && G.sima->flag & SI_SYNC_UVSEL) {
2762                 return (efa->h==0);
2763         } else {
2764                 return (efa->h==0 && efa->f & SELECT);
2765         }
2766         return 0;
2767 }
2768
2769 int simaFaceDraw_Check( EditFace *efa, MTFace *tf )
2770 {
2771         if (G.sima && G.sima->flag & SI_LOCAL_UV) {
2772                 if (tf->tpage==G.sima->image) {
2773                         return simaFaceDraw_Check_nolocal(efa);
2774                 } else {
2775                         return 0;
2776                 }
2777         } else {
2778                 return simaFaceDraw_Check_nolocal(efa);
2779         }
2780 }
2781
2782 int simaFaceSel_Check( struct EditFace *efa, struct MTFace *tf )
2783 {
2784         if (G.sima && G.sima->flag & SI_SYNC_UVSEL) {
2785                 return (efa->f & SELECT);
2786         } else {
2787                 return (!(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) &&(!efa->v4 || tf->flag & TF_SEL4));
2788         }
2789 }
2790
2791 void simaFaceSel_Set( struct EditFace *efa, struct MTFace *tf )
2792 {
2793         if (G.sima && G.sima->flag & SI_SYNC_UVSEL) {
2794                 EM_select_face(efa, 1);
2795         } else {
2796                 tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2797         }
2798 }
2799
2800 void simaFaceSel_UnSet( struct EditFace *efa, struct MTFace *tf )
2801 {
2802         if (G.sima && G.sima->flag & SI_SYNC_UVSEL) {
2803                 EM_select_face(efa, 0);
2804         } else {
2805                 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2806         }
2807 }
2808
2809 int simaUVSel_Check( struct EditFace *efa, struct MTFace *tf, int i)
2810 {
2811         if (G.sima && G.sima->flag & SI_SYNC_UVSEL) {
2812                 if (G.scene->selectmode == SCE_SELECT_FACE) {
2813                         return efa->f & SELECT;
2814                 } else {
2815                         return (*(&efa->v1 + i))->f & SELECT;
2816                 }
2817         } else {
2818                 return tf->flag & TF_SEL_MASK(i);
2819         }
2820 }
2821
2822 void simaUVSel_Set( struct EditFace *efa, struct MTFace *tf, int i)
2823 {
2824         if (G.sima && G.sima->flag & SI_SYNC_UVSEL) {
2825                 if (G.scene->selectmode == SCE_SELECT_FACE) {
2826                         EM_select_face(efa, 1);
2827                 } else {
2828                         (*(&efa->v1 + i))->f |= SELECT;
2829                 }
2830         } else {
2831                 tf->flag |= TF_SEL_MASK(i);
2832         }
2833 }
2834
2835 void simaUVSel_UnSet( struct EditFace *efa, struct MTFace *tf, int i)
2836 {
2837         if (G.sima && G.sima->flag & SI_SYNC_UVSEL) {
2838                 if (G.scene->selectmode == SCE_SELECT_FACE) {
2839                         EM_select_face(efa, 0);
2840                 } else {
2841                         (*(&efa->v1 + i))->f &= ~SELECT;
2842                 }
2843         } else {
2844                 tf->flag &= ~TF_SEL_MASK(i);
2845         }
2846 }
2847