made sticky UV editing options more accessible by adding them to a popup in the header.
[blender.git] / source / blender / src / editsima.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <stdlib.h>
34 #include <string.h>
35 #include <math.h>
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #ifndef WIN32
42 #include <unistd.h>
43 #else
44 #include <io.h>
45 #endif   
46 #include "MEM_guardedalloc.h"
47
48 #include "BLI_blenlib.h"
49 #include "BLI_arithb.h"
50 #include "BLI_editVert.h"
51
52 #include "IMB_imbuf_types.h"
53 #include "IMB_imbuf.h"
54
55 #include "DNA_image_types.h"
56 #include "DNA_mesh_types.h"
57 #include "DNA_meshdata_types.h"
58 #include "DNA_node_types.h"
59 #include "DNA_object_types.h" // only for uvedit_selectionCB() (struct Object)
60 #include "DNA_packedFile_types.h"
61 #include "DNA_scene_types.h"
62 #include "DNA_space_types.h"
63 #include "DNA_screen_types.h"
64 #include "DNA_texture_types.h"
65 #include "DNA_userdef_types.h"
66 #include "DNA_view3d_types.h"
67
68 #include "BKE_colortools.h"
69 #include "BKE_depsgraph.h"
70 #include "BKE_displist.h"
71 #include "BKE_image.h"
72 #include "BKE_global.h"
73 #include "BKE_library.h"
74 #include "BKE_main.h"
75 #include "BKE_mesh.h"
76 #include "BKE_node.h"
77 #include "BKE_object.h"
78 #include "BKE_packedFile.h"
79 #include "BKE_utildefines.h"
80
81 #include "BIF_gl.h"
82 #include "BIF_glutil.h"
83 #include "BIF_imasel.h"
84 #include "BIF_interface.h"
85 #include "BIF_drawimage.h"
86 #include "BIF_editview.h"
87 #include "BIF_editsima.h"
88 #include "BIF_mywindow.h"
89 #include "BIF_previewrender.h"
90 #include "BIF_screen.h"
91 #include "BIF_space.h"
92 #include "BIF_toolbox.h"
93 #include "BIF_transform.h"
94 #include "BIF_writeimage.h"
95 #include "BIF_editmesh.h"
96
97 #include "BSE_drawipo.h"
98 #include "BSE_edit.h"
99 #include "BSE_filesel.h"
100 #include "BSE_trans_types.h"
101
102 #include "BDR_editobject.h"
103 #include "BDR_unwrapper.h"
104
105 #include "BMF_Api.h"
106
107 #include "RE_pipeline.h"
108
109 #include "blendef.h"
110 #include "multires.h"
111 #include "mydevice.h"
112 #include "editmesh.h"
113
114 /* local prototypes */
115 void sel_uvco_inside_radius(short , EditFace *efa, MTFace *, int , float *, float *, short);
116 void uvedit_selectionCB(short , Object *, short *, float ); /* used in edit.c*/ 
117
118 void object_uvs_changed(Object *ob)
119 {
120         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
121
122         allqueue(REDRAWVIEW3D, 0);
123         allqueue(REDRAWIMAGE, 0);
124 }
125
126 void object_tface_flags_changed(Object *ob, int updateButtons)
127 {
128         if (updateButtons) allqueue(REDRAWBUTSEDIT, 0);
129         allqueue(REDRAWVIEW3D, 0);
130         allqueue(REDRAWIMAGE, 0);
131 }
132
133 int is_uv_tface_editing_allowed_silent(void)
134 {
135         if(!EM_texFaceCheck()) return 0;
136         if(G.sima->mode!=SI_TEXTURE) return 0;
137         if(multires_level1_test()) return 0;    
138         return 1;
139 }
140
141 int is_uv_tface_editing_allowed(void)
142 {
143         if(!G.obedit) error("Enter Edit Mode to perform this action");
144
145         return is_uv_tface_editing_allowed_silent();
146 }
147
148 void get_connected_limit_tface_uv(float *limit)
149 {
150         ImBuf *ibuf= BKE_image_get_ibuf(G.sima->image, &G.sima->iuser);
151         if(ibuf && ibuf->x > 0 && ibuf->y > 0) {
152                 limit[0]= 0.05/(float)ibuf->x;
153                 limit[1]= 0.05/(float)ibuf->y;
154         }
155         else
156                 limit[0]= limit[1]= 0.05/256.0;
157 }
158
159 void be_square_tface_uv(EditMesh *em)
160 {
161         EditFace *efa;
162         MTFace *tface;
163         /* if 1 vertex selected: doit (with the selected vertex) */
164         for (efa= em->faces.first; efa; efa= efa->next) {
165                 if (efa->v4) {
166                         tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
167                         if (SIMA_FACEDRAW_CHECK(efa, tface)) {
168                                 if (SIMA_UVSEL_CHECK(efa, tface, 0)) {
169                                         if( tface->uv[1][0] == tface->uv[2][0] ) {
170                                                 tface->uv[1][1]= tface->uv[0][1];
171                                                 tface->uv[3][0]= tface->uv[0][0];
172                                         }
173                                         else {  
174                                                 tface->uv[1][0]= tface->uv[0][0];
175                                                 tface->uv[3][1]= tface->uv[0][1];
176                                         }
177                                         
178                                 }
179                                 if (SIMA_UVSEL_CHECK(efa, tface, 1)) {
180                                         if( tface->uv[2][1] == tface->uv[3][1] ) {
181                                                 tface->uv[2][0]= tface->uv[1][0];
182                                                 tface->uv[0][1]= tface->uv[1][1];
183                                         }
184                                         else {
185                                                 tface->uv[2][1]= tface->uv[1][1];
186                                                 tface->uv[0][0]= tface->uv[1][0];
187                                         }
188
189                                 }
190                                 if (SIMA_UVSEL_CHECK(efa, tface, 2)) {
191                                         if( tface->uv[3][0] == tface->uv[0][0] ) {
192                                                 tface->uv[3][1]= tface->uv[2][1];
193                                                 tface->uv[1][0]= tface->uv[2][0];
194                                         }
195                                         else {
196                                                 tface->uv[3][0]= tface->uv[2][0];
197                                                 tface->uv[1][1]= tface->uv[2][1];
198                                         }
199                                 }
200                                 if (SIMA_UVSEL_CHECK(efa, tface, 3)) {
201                                         if( tface->uv[0][1] == tface->uv[1][1] ) {
202                                                 tface->uv[0][0]= tface->uv[3][0];
203                                                 tface->uv[2][1]= tface->uv[3][1];
204                                         }
205                                         else  {
206                                                 tface->uv[0][1]= tface->uv[3][1];
207                                                 tface->uv[2][0]= tface->uv[3][0];
208                                         }
209
210                                 }
211                         }
212                 }
213         }
214 }
215
216 void transform_aspect_ratio_tface_uv(float *aspx, float *aspy)
217 {
218         int w, h;
219         float xuser_asp, yuser_asp;
220         
221         aspect_sima(G.sima, &xuser_asp, &yuser_asp);
222         
223         transform_width_height_tface_uv(&w, &h);
224         *aspx= (float)w/256.0f * xuser_asp;
225         *aspy= (float)h/256.0f * yuser_asp;
226 }
227
228 void transform_width_height_tface_uv(int *width, int *height)
229 {
230         ImBuf *ibuf= BKE_image_get_ibuf(G.sima->image, &G.sima->iuser);
231
232         if(ibuf) {
233                 *width= ibuf->x;
234                 *height= ibuf->y;
235         }
236         else {
237                 *width= 256;
238                 *height= 256;
239         }
240 }
241
242 void mirror_tface_uv(char mirroraxis)
243 {
244         if (mirroraxis == 'x')
245                 Mirror(1); /* global x */
246         else if (mirroraxis == 'y')
247                 Mirror(2); /* global y */
248 }
249
250 void mirrormenu_tface_uv(void)
251 {
252         short mode= 0;
253
254         if( is_uv_tface_editing_allowed()==0 ) return;
255
256         mode= pupmenu("Mirror%t|X Axis%x1|Y Axis%x2|");
257
258         if(mode==-1) return;
259
260         if(mode==1) mirror_tface_uv('x');
261         else if(mode==2) mirror_tface_uv('y');
262
263         BIF_undo_push("Mirror UV");
264 }
265
266 void weld_align_tface_uv(char tool)
267 {
268         EditMesh *em = G.editMesh;
269         EditFace *efa;
270         MTFace *tface;
271         float cent[2];
272         
273         if( is_uv_tface_editing_allowed()==0 ) return;
274         cent_tface_uv(cent, 0);
275
276         if(tool == 'x' || tool == 'w') {
277                 for (efa= em->faces.first; efa; efa= efa->next) {
278                         tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
279                         if (SIMA_FACEDRAW_CHECK(efa, tface)) {
280                                 if (SIMA_UVSEL_CHECK(efa, tface, 0))
281                                         tface->uv[0][0]= cent[0];
282                                 if (SIMA_UVSEL_CHECK(efa, tface, 1))
283                                         tface->uv[1][0]= cent[0];
284                                 if (SIMA_UVSEL_CHECK(efa, tface, 2))
285                                         tface->uv[2][0]= cent[0];
286                                 if (efa->v4 && SIMA_UVSEL_CHECK(efa, tface, 3))
287                                         tface->uv[3][0]= cent[0];
288                         }
289                 }
290         }
291
292         if(tool == 'y' || tool == 'w') {
293                 for (efa= em->faces.first; efa; efa= efa->next) {
294                         tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
295                         if (SIMA_FACEDRAW_CHECK(efa, tface)) {
296                                 if (SIMA_UVSEL_CHECK(efa, tface, 0))
297                                         tface->uv[0][1]= cent[1];
298                                 if (SIMA_UVSEL_CHECK(efa, tface, 1))
299                                         tface->uv[1][1]= cent[1];
300                                 if (SIMA_UVSEL_CHECK(efa, tface, 2))
301                                         tface->uv[2][1]= cent[1];
302                                 if (efa->v4 && SIMA_UVSEL_CHECK(efa, tface, 3))
303                                         tface->uv[3][1]= cent[1];
304                         }
305                 }
306         }
307
308         object_uvs_changed(OBACT);
309 }
310
311 void weld_align_menu_tface_uv(void)
312 {
313         short mode= 0;
314
315         if( is_uv_tface_editing_allowed()==0 ) return;
316
317         mode= pupmenu("Weld/Align%t|Weld%x1|Align X%x2|Align Y%x3|");
318
319         if(mode==-1) return;
320
321         if(mode==1) weld_align_tface_uv('w');
322         else if(mode==2) weld_align_tface_uv('x');
323         else if(mode==3) weld_align_tface_uv('y');
324
325         if(mode==1) BIF_undo_push("Weld UV");
326         else if(mode==2 || mode==3) BIF_undo_push("Align UV");
327 }
328
329 void select_invert_tface_uv(void)
330 {
331         EditMesh *em = G.editMesh;
332         EditFace *efa;
333         MTFace *tface;
334         
335         if( is_uv_tface_editing_allowed()==0 ) return;
336
337         if (G.sima->flag & SI_SYNC_UVSEL) {
338                 /* Warning, this is not that good (calling editmode stuff from UV),
339                 TODO look into changing it */
340                 selectswap_mesh();
341                 return;
342         } else {
343                 for (efa= em->faces.first; efa; efa= efa->next) {
344                         tface = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
345                         if (SIMA_FACEDRAW_CHECK(efa, tface)) {
346                                 tface->flag ^= TF_SEL1;
347                                 tface->flag ^= TF_SEL2;
348                                 tface->flag ^= TF_SEL3;
349                                 if(efa->v4) tface->flag ^= TF_SEL4;
350                         }
351                 }
352         }
353         BIF_undo_push("Select Inverse UV");
354
355         allqueue(REDRAWIMAGE, 0);
356 }
357
358 void select_swap_tface_uv(void)
359 {
360         EditMesh *em = G.editMesh;
361         EditFace *efa;
362         MTFace *tface;
363         int sel=0;
364         
365         if( is_uv_tface_editing_allowed()==0 ) return;
366         
367         if (G.sima->flag & SI_SYNC_UVSEL) {
368                 deselectall_mesh();
369                 return;
370         } else {
371                         
372                 for (efa= em->faces.first; efa; efa= efa->next) {
373                         tface = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
374                         if (SIMA_FACEDRAW_CHECK(efa, tface)) {
375                                 if(tface->flag & (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4)) {
376                                         sel= 1;
377                                         break;
378                                 }
379                         }
380                 }
381         
382                 for (efa= em->faces.first; efa; efa= efa->next) {
383                         tface = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
384                         if (SIMA_FACEDRAW_CHECK(efa, tface)) {
385                                 if(efa->v4) {
386                                         if(sel) tface->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
387                                         else tface->flag |= (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
388                                 }
389                                 else {
390                                         if(sel) tface->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
391                                         else tface->flag |= (TF_SEL1+TF_SEL2+TF_SEL3);
392                                 }
393                         }
394                 }
395         }
396         BIF_undo_push("Select swap");
397
398         allqueue(REDRAWIMAGE, 0);
399 }
400
401 static int msel_hit(float *limit, unsigned int *hitarray, unsigned int vertexid, float **uv, float *uv2, int sticky)
402 {
403         int i;
404         for(i=0; i< 4; i++) {
405                 if(hitarray[i] == vertexid) {
406                         if(sticky == 2) {
407                                 if(fabs(uv[i][0]-uv2[0]) < limit[0] &&
408                             fabs(uv[i][1]-uv2[1]) < limit[1])
409                                         return 1;
410                         }
411                         else return 1;
412                 }
413         }
414         return 0;
415 }
416
417 static void find_nearest_tface(MTFace **nearesttf, EditFace **nearestefa)
418 {
419         EditMesh *em= G.editMesh;
420         MTFace *tf;
421         EditFace *efa;
422         int i, nverts, mindist, dist, fcenter[2], uval[2];
423         short mval[2];
424
425         getmouseco_areawin(mval);       
426
427         mindist= 0x7FFFFFF;
428         *nearesttf= NULL;
429         *nearestefa= NULL;
430         
431         for (efa= em->faces.first; efa; efa= efa->next) {
432                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
433                 if (SIMA_FACEDRAW_CHECK(efa, tf)) {
434                         fcenter[0]= fcenter[1]= 0;
435                         nverts= efa->v4? 4: 3;
436                         for(i=0; i<nverts; i++) {
437                                 uvco_to_areaco_noclip(tf->uv[i], uval);
438                                 fcenter[0] += uval[0];
439                                 fcenter[1] += uval[1];
440                         }
441
442                         fcenter[0] /= nverts;
443                         fcenter[1] /= nverts;
444
445                         dist= abs(mval[0]- fcenter[0])+ abs(mval[1]- fcenter[1]);
446                         if (dist < mindist) {
447                                 *nearesttf= tf;
448                                 *nearestefa= efa;
449                                 mindist= dist;
450                         }
451                 }
452         }
453 }
454
455 static int nearest_uv_between(MTFace *tf, int nverts, int id, short *mval, int *uval)
456 {
457         float m[3], v1[3], v2[3], c1, c2;
458         int id1, id2;
459
460         id1= (id+nverts-1)%nverts;
461         id2= (id+nverts+1)%nverts;
462
463         m[0] = (float)(mval[0]-uval[0]);
464         m[1] = (float)(mval[1]-uval[1]);
465         Vec2Subf(v1, tf->uv[id1], tf->uv[id]);
466         Vec2Subf(v2, tf->uv[id2], tf->uv[id]);
467
468         /* m and v2 on same side of v-v1? */
469         c1= v1[0]*m[1] - v1[1]*m[0];
470         c2= v1[0]*v2[1] - v1[1]*v2[0];
471
472         if (c1*c2 < 0.0f)
473                 return 0;
474
475         /* m and v1 on same side of v-v2? */
476         c1= v2[0]*m[1] - v2[1]*m[0];
477         c2= v2[0]*v1[1] - v2[1]*v1[0];
478
479         return (c1*c2 >= 0.0f);
480 }
481
482 static void find_nearest_uv(MTFace **nearesttf, EditFace **nearestefa, unsigned int *nearestv, int *nearestuv)
483 {
484         EditMesh *em= G.editMesh;
485         EditFace *efa;
486         MTFace *tf;
487         int i, nverts, mindist, dist, uval[2];
488         short mval[2];
489
490         getmouseco_areawin(mval);       
491
492         mindist= 0x7FFFFFF;
493         *nearesttf= NULL;
494         *nearestefa= NULL;
495         
496         for (efa= em->faces.first; efa; efa= efa->next) {
497                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
498                 if (SIMA_FACEDRAW_CHECK(efa, tf)) {
499                         nverts= efa->v4? 4: 3;
500                         for(i=0; i<nverts; i++) {
501                                 uvco_to_areaco_noclip(tf->uv[i], uval);
502                                 dist= abs(mval[0]-uval[0]) + abs(mval[1]-uval[1]);
503
504                                 if (SIMA_UVSEL_CHECK(efa, tf, i))
505                                         dist += 5;
506
507                                 if(dist<=mindist) {
508                                         if(dist==mindist)
509                                                 if (!nearest_uv_between(tf, nverts, i, mval, uval))
510                                                         continue;
511
512                                         mindist= dist; 
513
514                                         *nearesttf= tf;
515                                         *nearestefa= efa;
516                                         *nearestuv= i;
517
518                                         if (i==0) *nearestv=  efa->v1->tmp.l;
519                                         else if (i==1) *nearestv=  efa->v2->tmp.l;
520                                         else if (i==2) *nearestv=  efa->v3->tmp.l;
521                                         else *nearestv=  efa->v4->tmp.l;
522                                 }
523                         }
524                 }
525         }
526 }
527
528 void mouse_select_sima(void) /* TODO - SYNCSEL */
529 {
530         EditMesh *em = G.editMesh;
531         EditFace *efa;
532         MTFace *tf, *nearesttf;
533         EditFace *nearestefa=NULL;
534         int a, selectsticky, actface, nearestuv, i;
535         char sticky;
536         short flush = 0; /* 0 == dont flush, 1 == sel, -1 == desel;  only use when selection sync is enabled */
537         unsigned int hitv[4], nearestv;
538         float *hituv[4], limit[2];
539         
540         if( is_uv_tface_editing_allowed()==0 ) return;
541
542         get_connected_limit_tface_uv(limit);
543         
544         if (G.sima->flag & SI_SYNC_UVSEL) {
545                 /* copy from mesh */
546                 if (G.scene->selectmode == SCE_SELECT_FACE) {
547                         actface= 1;
548                         sticky= 0;
549                 } else {
550                         actface= (G.qual & LR_ALTKEY || G.sima->flag & SI_SELACTFACE);
551                         sticky= 2;
552                 }
553         } else {
554                 /* normal operation */
555                 actface= (G.qual & LR_ALTKEY || G.sima->flag & SI_SELACTFACE);
556                 
557                 switch(G.sima->sticky) {
558                 case 0:
559                         sticky=2;
560                         break;
561                 case 1:
562                         sticky=0;
563                         break;
564                 case 2:
565                         if(G.qual & LR_CTRLKEY) {
566                                 sticky=0;
567                         } else {  
568                                 sticky=1;
569                         }
570                         break;
571                 }
572         }
573
574         if(actface) {
575                 find_nearest_tface(&nearesttf, &nearestefa);
576                 if(nearesttf==NULL)
577                         return;
578
579                 nearesttf->flag |= TF_ACTIVE;
580
581                 for (i=0; i<4; i++)
582                         hituv[i]= nearesttf->uv[i];
583
584                 hitv[0]= nearestefa->v1->tmp.l;
585                 hitv[1]= nearestefa->v2->tmp.l;
586                 hitv[2]= nearestefa->v3->tmp.l;
587                 
588                 if (nearestefa->v4)     hitv[3]= nearestefa->v4->tmp.l;
589                 else                            hitv[3]= 0xFFFFFFFF;
590         }
591         else {
592                 find_nearest_uv(&nearesttf, &nearestefa, &nearestv, &nearestuv);
593                 if(nearesttf==NULL)
594                         return;
595
596                 if(sticky) {
597                         for(i=0; i<4; i++)
598                                 hitv[i]= 0xFFFFFFFF;
599                         hitv[nearestuv]= nearestv;
600                         hituv[nearestuv]= nearesttf->uv[nearestuv];
601                 }
602         }
603
604         if(G.qual & LR_SHIFTKEY) {
605                 /* (de)select face */
606                 if(actface) {
607                         if(SIMA_FACESEL_CHECK(nearestefa, nearesttf)) {
608                                 SIMA_FACESEL_UNSET(nearestefa, nearesttf);
609                                 selectsticky= 0;
610                         }
611                         else {
612                                 SIMA_FACESEL_SET(nearestefa, nearesttf);
613                                 selectsticky= 1;
614                         }
615                         flush = -1;
616                 }
617                 /* (de)select uv node */
618                 else {
619                         if (SIMA_UVSEL_CHECK(nearestefa, nearesttf, nearestuv)) {
620                                 SIMA_UVSEL_UNSET(nearestefa, nearesttf, nearestuv);
621                                 selectsticky= 0;
622                         }
623                         else {
624                                 SIMA_UVSEL_SET(nearestefa, nearesttf, nearestuv);
625                                 selectsticky= 1;
626                         }
627                         flush = 1;
628                 }
629
630                 /* (de)select sticky uv nodes */
631                 if(sticky || actface) {
632                         EditVert *ev;
633                         
634                         for (a=0, ev=em->verts.first; ev; ev = ev->next, a++)
635                                 ev->tmp.l = a;
636                         
637                         /* deselect */
638                         if(selectsticky==0) {
639                                 for (efa= em->faces.first; efa; efa= efa->next) {
640                                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
641                                         if (SIMA_FACEDRAW_CHECK(efa, tf)) {
642                                                 /*if(nearesttf && tf!=nearesttf) tf->flag &=~ TF_ACTIVE;*/ /* TODO - deal with editmesh active face */
643                                                 if (!sticky) continue;
644         
645                                                 if(msel_hit(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
646                                                         SIMA_UVSEL_UNSET(efa, tf, 0);
647                                                 if(msel_hit(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
648                                                         SIMA_UVSEL_UNSET(efa, tf, 1);
649                                                 if(msel_hit(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
650                                                         SIMA_UVSEL_UNSET(efa, tf, 2);
651                                                 if (efa->v4)
652                                                         if(msel_hit(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
653                                                                 SIMA_UVSEL_UNSET(efa, tf, 3);
654                                         }
655                                 }
656                                 flush = -1;
657                         }
658                         /* select */
659                         else {
660                                 for (efa= em->faces.first; efa; efa= efa->next) {
661                                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
662                                         if (SIMA_FACEDRAW_CHECK(efa, tf)) {
663                                                 if(nearesttf && tf!=nearesttf)
664                                                         tf->flag &=~ TF_ACTIVE;
665                                                 if (!sticky) continue;
666         
667                                                 if(msel_hit(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
668                                                         SIMA_UVSEL_SET(efa, tf, 0);
669                                                 if(msel_hit(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
670                                                         SIMA_UVSEL_SET(efa, tf, 1);
671                                                 if(msel_hit(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
672                                                         SIMA_UVSEL_SET(efa, tf, 2);
673                                                 if (efa->v4)
674                                                         if(msel_hit(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
675                                                                 SIMA_UVSEL_SET(efa, tf, 3);
676                                         }
677                                 }
678                                 flush = 1;
679                         }                       
680                 }
681         }
682         else {
683                 /* select face and deselect other faces */ 
684                 if(actface) {
685                         for (efa= em->faces.first; efa; efa= efa->next) {
686                                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
687                                 SIMA_FACESEL_UNSET(efa, tf);
688                                 //if(nearesttf && tf!=nearesttf) /* TODO - deal with editmesh active face */
689                                 //      tf->flag &= ~TF_ACTIVE;
690                         }
691                         if(nearesttf)
692                                 SIMA_FACESEL_SET(nearestefa, nearesttf);
693                 }
694
695                 /* deselect uvs, and select sticky uvs */
696                 for (efa= em->faces.first; efa; efa= efa->next) {
697                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
698                         if (SIMA_FACEDRAW_CHECK(efa, tf)) {
699                                 if(!actface) SIMA_FACESEL_UNSET(efa, tf);
700                                 if(!sticky) continue;
701
702                                 if(msel_hit(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
703                                         SIMA_UVSEL_SET(efa, tf, 0);
704                                 if(msel_hit(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
705                                         SIMA_UVSEL_SET(efa, tf, 1);
706                                 if(msel_hit(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
707                                         SIMA_UVSEL_SET(efa, tf, 2);
708                                 if(efa->v4)
709                                         if(msel_hit(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
710                                                 SIMA_UVSEL_SET(efa, tf, 3);
711                                 flush= 1;
712                         }
713                 }
714                 
715                 if(!actface) {
716                         SIMA_UVSEL_SET(nearestefa, nearesttf, nearestuv);
717                         flush= 1;
718                 }
719         }
720         
721         force_draw(1);
722         
723         if (G.sima->flag & SI_SYNC_UVSEL) {
724                 /* flush for mesh selection */
725                 if (G.scene->selectmode != SCE_SELECT_FACE) {
726                         if (flush==1)           EM_select_flush();
727                         else if (flush==-1)     EM_deselect_flush();
728                 }
729                 allqueue(REDRAWVIEW3D, 0); /* mesh selection has changed */
730         }
731         
732         BIF_undo_push("Select UV");
733         rightmouse_transform();
734 }
735
736 void borderselect_sima(short whichuvs)
737 {
738         EditMesh *em = G.editMesh;
739         EditFace *efa;
740         MTFace *tface;
741         rcti rect;
742         rctf rectf;
743         int val;
744         short mval[2];
745
746         if( is_uv_tface_editing_allowed()==0) return;
747
748         val= get_border(&rect, 3);
749
750         if(val) {
751                 mval[0]= rect.xmin;
752                 mval[1]= rect.ymin;
753                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
754                 mval[0]= rect.xmax;
755                 mval[1]= rect.ymax;
756                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
757
758                 for (efa= em->faces.first; efa; efa= efa->next) {
759                         tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
760                         if (SIMA_FACEDRAW_CHECK(efa, tface)) {
761                                 if (whichuvs == UV_SELECT_ALL || (G.sima->flag & SI_SYNC_UVSEL) ) {
762                                         /* SI_SYNC_UVSEL - cant do pinned selection */
763                                         if(BLI_in_rctf(&rectf, (float)tface->uv[0][0], (float)tface->uv[0][1])) {
764                                                 if(val==LEFTMOUSE)      SIMA_UVSEL_SET(efa, tface, 0);
765                                                 else                            SIMA_UVSEL_UNSET(efa, tface, 0);
766                                         }
767                                         if(BLI_in_rctf(&rectf, (float)tface->uv[1][0], (float)tface->uv[1][1])) {
768                                                 if(val==LEFTMOUSE)      SIMA_UVSEL_SET(efa, tface, 1);
769                                                 else                            SIMA_UVSEL_UNSET(efa, tface, 1);
770                                         }
771                                         if(BLI_in_rctf(&rectf, (float)tface->uv[2][0], (float)tface->uv[2][1])) {
772                                                 if(val==LEFTMOUSE)      SIMA_UVSEL_SET(efa, tface, 2);
773                                                 else                            SIMA_UVSEL_UNSET(efa, tface, 2);
774                                         }
775                                         if(efa->v4 && BLI_in_rctf(&rectf, (float)tface->uv[3][0], (float)tface->uv[3][1])) {
776                                                 if(val==LEFTMOUSE)      SIMA_UVSEL_SET(efa, tface, 3);
777                                                 else                            SIMA_UVSEL_UNSET(efa, tface, 3);
778                                         }
779                                 } else if (whichuvs == UV_SELECT_PINNED) {
780                                         if ((tface->unwrap & TF_PIN1) && 
781                                                 BLI_in_rctf(&rectf, (float)tface->uv[0][0], (float)tface->uv[0][1])) {
782                                                 
783                                                 if(val==LEFTMOUSE)      SIMA_UVSEL_SET(efa, tface, 0);
784                                                 else                            SIMA_UVSEL_UNSET(efa, tface, 0);
785                                         }
786                                         if ((tface->unwrap & TF_PIN2) && 
787                                                 BLI_in_rctf(&rectf, (float)tface->uv[1][0], (float)tface->uv[1][1])) {
788                                                 
789                                                 if(val==LEFTMOUSE)      SIMA_UVSEL_SET(efa, tface, 1);
790                                                 else                            SIMA_UVSEL_UNSET(efa, tface, 1);
791                                         }
792                                         if ((tface->unwrap & TF_PIN3) && 
793                                                 BLI_in_rctf(&rectf, (float)tface->uv[2][0], (float)tface->uv[2][1])) {
794                                                 
795                                                 if(val==LEFTMOUSE)      SIMA_UVSEL_SET(efa, tface, 2);
796                                                 else                            SIMA_UVSEL_UNSET(efa, tface, 2);
797                                         }
798                                         if ((efa->v4) && (tface->unwrap & TF_PIN4) && BLI_in_rctf(&rectf, (float)tface->uv[3][0], (float)tface->uv[3][1])) {
799                                                 if(val==LEFTMOUSE)      SIMA_UVSEL_SET(efa, tface, 3);
800                                                 else                            SIMA_UVSEL_UNSET(efa, tface, 3);
801                                         }
802                                 }
803                         }
804                 }
805                 
806                 /* make sure newly selected vert selection is updated*/
807                 if (G.sima->flag & SI_SYNC_UVSEL) {
808                         if (G.scene->selectmode != SCE_SELECT_FACE) {
809                                 if (val==LEFTMOUSE)     EM_select_flush();
810                                 else                            EM_deselect_flush();
811                         }
812                         allqueue(REDRAWVIEW3D, 0); /* mesh selection has changed */
813                 }
814                 
815                 BIF_undo_push("Border select UV");
816                 scrarea_queue_winredraw(curarea);
817         }
818 }
819
820 int snap_uv_sel_to_curs(void)
821 {
822         EditMesh *em = G.editMesh;
823         EditFace *efa;
824         MTFace *tface;
825         short change = 0;
826
827         for (efa= em->faces.first; efa; efa= efa->next) {
828                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
829                 if (SIMA_FACEDRAW_CHECK(efa, tface)) {
830                         if (SIMA_UVSEL_CHECK(efa, tface, 0))            VECCOPY2D(tface->uv[0], G.v2d->cursor);
831                         if (SIMA_UVSEL_CHECK(efa, tface, 1))            VECCOPY2D(tface->uv[1], G.v2d->cursor);
832                         if (SIMA_UVSEL_CHECK(efa, tface, 2))            VECCOPY2D(tface->uv[2], G.v2d->cursor);
833                         if (efa->v4)
834                                 if (SIMA_UVSEL_CHECK(efa, tface, 3))    VECCOPY2D(tface->uv[3], G.v2d->cursor);
835                         change = 1;
836                 }
837         }
838         return change;
839 }
840
841 void snap_coord_to_pixel(float *uvco, float w, float h)
842 {
843         uvco[0] = ((float) ((int)((uvco[0]*w) + 0.5))) / w;  
844         uvco[1] = ((float) ((int)((uvco[1]*h) + 0.5))) / h;  
845 }
846
847 int snap_uv_sel_to_pixels(void) /* warning, sanity checks must alredy be done */
848 {
849         EditMesh *em = G.editMesh;
850         EditFace *efa;
851         MTFace *tface;
852         int wi, hi;
853         float w, h;
854         short change = 0;
855
856         transform_width_height_tface_uv(&wi, &hi);
857         w = (float)wi;
858         h = (float)hi;
859         
860         for (efa= em->faces.first; efa; efa= efa->next) {
861                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
862                 if (SIMA_FACEDRAW_CHECK(efa, tface)) {
863                         if (SIMA_UVSEL_CHECK(efa, tface, 0)) snap_coord_to_pixel(tface->uv[0], w, h);
864                         if (SIMA_UVSEL_CHECK(efa, tface, 1)) snap_coord_to_pixel(tface->uv[1], w, h);
865                         if (SIMA_UVSEL_CHECK(efa, tface, 2)) snap_coord_to_pixel(tface->uv[2], w, h);
866                         if (efa->v4)
867                                 if (SIMA_UVSEL_CHECK(efa, tface, 3)) snap_coord_to_pixel(tface->uv[3], w, h);
868                         change = 1;
869                 }
870         }
871         return change;
872 }
873
874 void snap_uv_curs_to_pixels(void)
875 {
876         int wi, hi;
877         float w, h;
878
879         transform_width_height_tface_uv(&wi, &hi);
880         w = (float)wi;
881         h = (float)hi;
882         snap_coord_to_pixel(G.v2d->cursor, w, h);
883 }
884
885 int snap_uv_curs_to_sel(void)
886 {
887         if( is_uv_tface_editing_allowed()==0 ) return 0;
888         return cent_tface_uv(G.v2d->cursor, 0);
889 }
890
891 void snap_menu_sima(void)
892 {
893         short event;
894         if( is_uv_tface_editing_allowed()==0 || !G.v2d) return; /* !G.v2d should never happen */
895         
896         event = pupmenu("Snap %t|Selection -> Pixels%x1|Selection -> Cursor%x2|Cursor-> Pixel%x3|Cursor-> Selection%x4");
897         switch (event) {
898                 case 1:
899                     if (snap_uv_sel_to_pixels()) {
900                         BIF_undo_push("Snap UV Selection to Pixels");
901                         object_uvs_changed(OBACT);
902                     }
903                     break;
904                 case 2:
905                     if (snap_uv_sel_to_curs()) {
906                         BIF_undo_push("Snap UV Selection to Cursor");
907                         object_uvs_changed(OBACT);
908                     }
909                     break;
910                 case 3:
911                     snap_uv_curs_to_pixels();
912                     scrarea_queue_winredraw(curarea);
913                     break;
914                 case 4:
915                     if (snap_uv_curs_to_sel())
916                         allqueue(REDRAWIMAGE, 0);
917                     break;
918         }
919 }
920
921
922 /** This is an ugly function to set the Tface selection flags depending
923   * on whether its UV coordinates are inside the normalized 
924   * area with radius rad and offset offset. These coordinates must be
925   * normalized to 1.0 
926   * Just for readability...
927   */
928
929 void sel_uvco_inside_radius(short sel, EditFace *efa, MTFace *tface, int index, float *offset, float *ell, short select_index)
930 {
931         // normalized ellipse: ell[0] = scaleX,
932         //                        [1] = scaleY
933
934         float *uv = tface->uv[index];
935         float x, y, r2;
936
937         x = (uv[0] - offset[0]) * ell[0];
938         y = (uv[1] - offset[1]) * ell[1];
939
940         r2 = x * x + y * y;
941         if (r2 < 1.0) {
942                 if (sel == LEFTMOUSE)   SIMA_UVSEL_SET(efa, tface, select_index);
943                 else                                    SIMA_UVSEL_UNSET(efa, tface, select_index);
944         }
945 }
946
947 // see below:
948 /** gets image dimensions of the 2D view 'v' */
949 static void getSpaceImageDimension(SpaceImage *sima, float *xy)
950 {
951         ImBuf *ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser);
952
953         if (ibuf) {
954                 xy[0] = ibuf->x * sima->zoom;
955                 xy[1] = ibuf->y * sima->zoom;
956         } else {
957                 xy[0] = 256 * sima->zoom;
958                 xy[1] = 256 * sima->zoom;
959         }
960 }
961
962 /** Callback function called by circle_selectCB to enable 
963   * brush select in UV editor.
964   */
965
966 void uvedit_selectionCB(short selecting, Object *editobj, short *mval, float rad) 
967 {
968         EditMesh *em = G.editMesh;
969         EditFace *efa;
970         float offset[2];
971         MTFace *tface;
972         float ellipse[2]; // we need to deal with ellipses, as
973                           // non square textures require for circle
974                                           // selection. this ellipse is normalized; r = 1.0
975
976         getSpaceImageDimension(curarea->spacedata.first, ellipse);
977         ellipse[0] /= rad;
978         ellipse[1] /= rad;
979
980         areamouseco_to_ipoco(G.v2d, mval, &offset[0], &offset[1]);
981         
982         if (selecting) {
983                 for (efa= em->faces.first; efa; efa= efa->next) {
984                         tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
985                         sel_uvco_inside_radius(selecting, efa, tface, 0, offset, ellipse, 0);
986                         sel_uvco_inside_radius(selecting, efa, tface, 1, offset, ellipse, 1);
987                         sel_uvco_inside_radius(selecting, efa, tface, 2, offset, ellipse, 2);
988                         if (efa->v4)
989                                 sel_uvco_inside_radius(selecting, efa, tface, 3, offset, ellipse, 3);
990                 }
991
992                 if(G.f & G_DRAWFACES) { /* full redraw only if necessary */
993                         draw_sel_circle(0, 0, 0, 0, 0); /* signal */
994                         force_draw(0);
995                 }
996                 else { /* force_draw() is no good here... */
997                         glDrawBuffer(GL_FRONT);
998                         draw_uvs_sima();
999                         bglFlush();
1000                         glDrawBuffer(GL_BACK);
1001                 }
1002                 
1003                 
1004                 if (selecting == LEFTMOUSE)     EM_select_flush();
1005                 else                                            EM_deselect_flush();
1006                 
1007                 if (G.sima->lock && (G.sima->flag & SI_SYNC_UVSEL))
1008                         force_draw_plus(SPACE_VIEW3D, 0);
1009         }
1010 }
1011
1012
1013 void mouseco_to_curtile(void)
1014 {
1015         float fx, fy;
1016         short mval[2];
1017         
1018         if( is_uv_tface_editing_allowed()==0) return;
1019
1020         if(G.sima->image && G.sima->image->tpageflag & IMA_TILES) {
1021                 
1022                 G.sima->flag |= SI_EDITTILE;
1023                 
1024                 while(get_mbut()&L_MOUSE) {
1025                         
1026                         calc_image_view(G.sima, 'f');
1027                         
1028                         getmouseco_areawin(mval);
1029                         areamouseco_to_ipoco(G.v2d, mval, &fx, &fy);
1030
1031                         if(fx>=0.0 && fy>=0.0 && fx<1.0 && fy<1.0) {
1032                         
1033                                 fx= (fx)*G.sima->image->xrep;
1034                                 fy= (fy)*G.sima->image->yrep;
1035                                 
1036                                 mval[0]= fx;
1037                                 mval[1]= fy;
1038                                 
1039                                 G.sima->curtile= mval[1]*G.sima->image->xrep + mval[0];
1040                         }
1041
1042                         scrarea_do_windraw(curarea);
1043                         screen_swapbuffers();
1044                 }
1045                 
1046                 G.sima->flag &= ~SI_EDITTILE;
1047
1048                 image_set_tile(G.sima, 2);
1049
1050                 allqueue(REDRAWVIEW3D, 0);
1051                 scrarea_queue_winredraw(curarea);
1052         }
1053 }
1054
1055 /* Could be used for other 2D views also */
1056 void mouseco_to_cursor_sima(void)
1057 {
1058         short mval[2];
1059         getmouseco_areawin(mval);
1060         areamouseco_to_ipoco(G.v2d, mval, &G.v2d->cursor[0], &G.v2d->cursor[1]);
1061         scrarea_queue_winredraw(curarea);
1062 }
1063
1064 void stitch_uv_tface(int mode)
1065 {
1066         MTFace *tf;
1067         int a, vtot;
1068         float newuv[2], limit[2];
1069         UvMapVert *vlist, *iterv, *v;
1070         EditMesh *em = G.editMesh;
1071         EditVert *ev;
1072         EditFace *efa;
1073         
1074         struct UvVertMap *vmap;
1075         
1076         
1077         if(is_uv_tface_editing_allowed()==0)
1078                 return;
1079         if(G.sima->flag & SI_SYNC_UVSEL) {
1080                 error("Can't stitch when Sync Mesh Selection is enabled");
1081                 return;
1082         }
1083         
1084         limit[0]= limit[1]= 20.0;
1085         if(mode==1) {
1086                 add_numbut(0, NUM|FLO, "Limit:", 0.1, 1000.0, &limit[0], NULL);
1087                 if (!do_clever_numbuts("Stitch UVs", 1, REDRAW))
1088                         return;
1089         }
1090
1091         limit[0]= limit[1]= limit[0]/256.0;
1092         if(G.sima->image) {
1093                 ImBuf *ibuf= BKE_image_get_ibuf(G.sima->image, &G.sima->iuser);
1094
1095                 if(ibuf && ibuf->x > 0 && ibuf->y > 0) {
1096                         limit[1]= limit[0]/(float)ibuf->y;
1097                         limit[0]= limit[0]/(float)ibuf->x;
1098                 }
1099         }
1100
1101         /*vmap= make_uv_vert_map(me->mface, tf, me->totface, me->totvert, 1, limit);*/
1102         EM_init_index_arrays(0, 0, 1);
1103         vmap= make_uv_vert_map_EM(1, 0, limit);
1104         if(vmap == NULL)
1105                 return;
1106
1107         if(mode==0) {
1108                 for(a=0, ev= em->verts.first; ev; a++, ev= ev->next) {
1109                         v = get_uv_map_vert_EM(vmap, a);
1110
1111                         if(v == NULL)
1112                                 continue;
1113
1114                         newuv[0]= 0; newuv[1]= 0;
1115                         vtot= 0;
1116
1117                         for(iterv=v; iterv; iterv=iterv->next) {
1118                                 efa = EM_get_face_for_index(iterv->f);
1119                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1120                                 if (tf->flag & TF_SEL_MASK(iterv->tfindex)) {
1121                                         newuv[0] += tf->uv[iterv->tfindex][0];
1122                                         newuv[1] += tf->uv[iterv->tfindex][1];
1123                                         vtot++;
1124                                 }
1125                         }
1126
1127                         if (vtot > 1) {
1128                                 newuv[0] /= vtot; newuv[1] /= vtot;
1129
1130                                 for(iterv=v; iterv; iterv=iterv->next) {
1131                                         efa = EM_get_face_for_index(iterv->f);
1132                                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1133                                         if (tf->flag & TF_SEL_MASK(iterv->tfindex)) {
1134                                                 tf->uv[iterv->tfindex][0]= newuv[0];
1135                                                 tf->uv[iterv->tfindex][1]= newuv[1];
1136                                         }
1137                                 }
1138                         }
1139                 }
1140         } else if(mode==1) {
1141                 for(a=0, ev= em->verts.first; ev; a++, ev= ev->next) {
1142                         vlist= get_uv_map_vert_EM(vmap, a);
1143
1144                         while(vlist) {
1145                                 newuv[0]= 0; newuv[1]= 0;
1146                                 vtot= 0;
1147
1148                                 for(iterv=vlist; iterv; iterv=iterv->next) {
1149                                         if((iterv != vlist) && iterv->separate)
1150                                                 break;
1151                                         efa = EM_get_face_for_index(iterv->f);
1152                                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1153                                         
1154                                         if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
1155                                                 newuv[0] += tf->uv[iterv->tfindex][0];
1156                                                 newuv[1] += tf->uv[iterv->tfindex][1];
1157                                                 vtot++;
1158                                         }
1159                                 }
1160
1161                                 if (vtot > 1) {
1162                                         newuv[0] /= vtot; newuv[1] /= vtot;
1163
1164                                         for(iterv=vlist; iterv; iterv=iterv->next) {
1165                                                 if((iterv != vlist) && iterv->separate)
1166                                                         break;
1167                                                 efa = EM_get_face_for_index(iterv->f);
1168                                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1169                                                 if (tf->flag & TF_SEL_MASK(iterv->tfindex)) {
1170                                                         tf->uv[iterv->tfindex][0]= newuv[0];
1171                                                         tf->uv[iterv->tfindex][1]= newuv[1];
1172                                                 }
1173                                         }
1174                                 }
1175                                 vlist= iterv;
1176                         }
1177                 }
1178         }
1179
1180         free_uv_vert_map_EM(vmap);
1181         EM_free_index_arrays();
1182         
1183         if(G.sima->flag & SI_BE_SQUARE) be_square_tface_uv(em);
1184
1185         BIF_undo_push("Stitch UV");
1186
1187         object_uvs_changed(OBACT);
1188 }
1189
1190 void select_linked_tface_uv(int mode) /* TODO */
1191 {
1192         EditMesh *em= G.editMesh;
1193         EditFace *efa, *nearestefa=NULL;
1194         MTFace *tf, *nearesttf=NULL;
1195         UvVertMap *vmap;
1196         UvMapVert *vlist, *iterv, *startv;
1197         unsigned int *stack, stacksize= 0, nearestv;
1198         char *flag;
1199         int a, nearestuv, i, nverts, j;
1200         float limit[2];
1201         if(is_uv_tface_editing_allowed()==0)
1202                 return;
1203
1204         if(G.sima->flag & SI_SYNC_UVSEL) {
1205                 error("Can't select linked when Sync Mesh Selection is enabled");
1206                 return;
1207         }
1208         
1209         if (mode == 2) {
1210                 nearesttf= NULL;
1211                 nearestuv= 0;
1212         }
1213         if (mode!=2) {
1214                 find_nearest_uv(&nearesttf, &nearestefa, &nearestv, &nearestuv);
1215                 if(nearesttf==NULL)
1216                         return;
1217         }
1218
1219         get_connected_limit_tface_uv(limit);
1220         vmap= make_uv_vert_map_EM(1, 1, limit);
1221         if(vmap == NULL)
1222                 return;
1223
1224         stack= MEM_mallocN(sizeof(*stack)* BLI_countlist(&em->faces), "UvLinkStack");
1225         flag= MEM_callocN(sizeof(*flag)*BLI_countlist(&em->faces), "UvLinkFlag");
1226
1227         if (mode == 2) {
1228                 for (a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
1229                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1230                         if (SIMA_FACEDRAW_CHECK(efa, tf)) {
1231                                 if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) {
1232                                         stack[stacksize]= a;
1233                                         stacksize++;
1234                                         flag[a]= 1;
1235                                 }
1236                         }
1237                 }
1238         } else {
1239                 for (a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
1240                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1241                         if(tf == nearesttf) {
1242                                 stack[stacksize]= a;
1243                                 stacksize++;
1244                                 flag[a]= 1;
1245                                 break;
1246                         }
1247                 }
1248         }
1249
1250         while(stacksize > 0) {
1251                 stacksize--;
1252                 a= stack[stacksize];
1253                 
1254                 for (j=0, efa= em->faces.first; efa; efa= efa->next, j++) {
1255                         if (j==a) {
1256                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1257                                 break;
1258                         }
1259                 }
1260
1261                 nverts= efa->v4? 4: 3;
1262
1263                 for(i=0; i<nverts; i++) {
1264                         /* make_uv_vert_map_EM sets verts tmp.l to the indicies */
1265                         vlist= get_uv_map_vert_EM(vmap, (*(&efa->v1 + i))->tmp.l);
1266                         
1267                         startv= vlist;
1268
1269                         for(iterv=vlist; iterv; iterv=iterv->next) {
1270                                 if(iterv->separate)
1271                                         startv= iterv;
1272                                 if(iterv->f == a)
1273                                         break;
1274                         }
1275
1276                         for(iterv=startv; iterv; iterv=iterv->next) {
1277                                 if((startv != iterv) && (iterv->separate))
1278                                         break;
1279                                 else if(!flag[iterv->f]) {
1280                                         flag[iterv->f]= 1;
1281                                         stack[stacksize]= iterv->f;;
1282                                         stacksize++;
1283                                 }
1284                         }
1285                 }
1286         }
1287
1288         if(mode==0 || mode==2) {
1289                 for (a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
1290                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1291                         if(flag[a])
1292                                 tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1293                         else
1294                                 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1295                 }
1296         }
1297         else if(mode==1) {
1298                 for (a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
1299                         if(flag[a]) {
1300                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1301                                 if (efa->v4) {
1302                                         if((tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)))
1303                                                 break;
1304                                 }
1305                                 else if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
1306                                         break;
1307                         }
1308                 }
1309
1310                 if (efa) {
1311                         for (a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
1312                                 if(flag[a]) {
1313                                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1314                                         tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1315                                 }
1316                         }
1317                 }
1318                 else {
1319                         for (a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
1320                                 if(flag[a]) {
1321                                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1322                                         tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1323                                 }
1324                         }
1325                 }
1326         }
1327         
1328         MEM_freeN(stack);
1329         MEM_freeN(flag);
1330         free_uv_vert_map_EM(vmap);
1331
1332         BIF_undo_push("Select linked UV");
1333         scrarea_queue_winredraw(curarea);
1334 }
1335
1336 void unlink_selection(void)
1337 {
1338         EditMesh *em= G.editMesh;
1339         EditFace *efa;
1340         MTFace *tface;
1341
1342         if( is_uv_tface_editing_allowed()==0 ) return;
1343
1344         if(G.sima->flag & SI_SYNC_UVSEL) {
1345                 error("Can't select unlinked when Sync Mesh Selection is enabled");
1346                 return;
1347         }
1348         
1349         for (efa= em->faces.first; efa; efa= efa->next) {
1350                 tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1351                 if (SIMA_FACEDRAW_CHECK(efa, tface)) {
1352                         if(efa->v4) {
1353                                 if(~tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4))
1354                                         tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1355                         } else {
1356                                 if(~tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
1357                                         tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3);
1358                         }
1359                 }
1360         }
1361         
1362         BIF_undo_push("Unlink UV selection");
1363         scrarea_queue_winredraw(curarea);
1364 }
1365
1366 /*
1367 void toggle_uv_select(int mode)
1368 {
1369         switch(mode){
1370         case 'f':
1371                 G.sima->flag ^= SI_SELACTFACE;
1372                 break;
1373         case 's':
1374                 G.sima->flag &= ~SI_LOCALSTICKY;
1375                 G.sima->flag |= SI_STICKYUVS;
1376                 break;
1377         case 'l':
1378                 G.sima->flag &= ~SI_STICKYUVS;
1379                 G.sima->flag &= ~SI_LOCALSTICKY;
1380                 break;
1381         case 'o':
1382                  G.sima->flag &= ~SI_STICKYUVS;
1383                  G.sima->flag |= SI_LOCALSTICKY;
1384                 break;
1385         }
1386         allqueue(REDRAWIMAGE, 0);
1387 }
1388 */
1389
1390 void pin_tface_uv(int mode)
1391 {
1392         EditMesh *em = G.editMesh;
1393         EditFace *efa;
1394         MTFace *tface;
1395         
1396         if( is_uv_tface_editing_allowed()==0 ) return;
1397         
1398         for (efa= em->faces.first; efa; efa= efa->next) {
1399                 tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1400                 if (SIMA_FACEDRAW_CHECK(efa, tface)) {
1401                         if(mode ==1) {
1402                                 if(SIMA_UVSEL_CHECK(efa, tface, 0)) tface->unwrap |= TF_PIN1;
1403                                 if(SIMA_UVSEL_CHECK(efa, tface, 1)) tface->unwrap |= TF_PIN2;
1404                                 if(SIMA_UVSEL_CHECK(efa, tface, 2)) tface->unwrap |= TF_PIN3;
1405                                 if(efa->v4)
1406                                         if(SIMA_UVSEL_CHECK(efa, tface, 3)) tface->unwrap |= TF_PIN4;
1407                         }
1408                         else if (mode ==0) {
1409                                 if(SIMA_UVSEL_CHECK(efa, tface, 0)) tface->unwrap &= ~TF_PIN1;
1410                                 if(SIMA_UVSEL_CHECK(efa, tface, 1)) tface->unwrap &= ~TF_PIN2;
1411                                 if(SIMA_UVSEL_CHECK(efa, tface, 2)) tface->unwrap &= ~TF_PIN3;
1412                                 if(efa->v4)
1413                                         if(SIMA_UVSEL_CHECK(efa, tface, 3)) tface->unwrap &= ~TF_PIN4;
1414                         }
1415                 }
1416         }
1417         
1418         BIF_undo_push("Pin UV");
1419         scrarea_queue_winredraw(curarea);
1420 }
1421
1422 void select_pinned_tface_uv(void)
1423 {
1424         EditMesh *em= G.editMesh;
1425         EditFace *efa;
1426         MTFace *tface;
1427         
1428         if( is_uv_tface_editing_allowed()==0 ) return;
1429         
1430         for (efa= em->faces.first; efa; efa= efa->next) {
1431                 tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1432                 if (SIMA_FACEDRAW_CHECK(efa, tface)) {
1433                         if (tface->unwrap & TF_PIN1) SIMA_UVSEL_SET(efa, tface, 0);
1434                         if (tface->unwrap & TF_PIN2) SIMA_UVSEL_SET(efa, tface, 1);
1435                         if (tface->unwrap & TF_PIN3) SIMA_UVSEL_SET(efa, tface, 2);
1436                         if(efa->v4) {
1437                                 if (tface->unwrap & TF_PIN4) SIMA_UVSEL_SET(efa, tface, 3);
1438                         }
1439                         
1440                 }
1441         }
1442         
1443         if (G.sima->flag & SI_SYNC_UVSEL) {
1444                 allqueue(REDRAWVIEW3D, 0); /* mesh selection has changed */
1445         }
1446         
1447         BIF_undo_push("Select Pinned UVs");
1448         scrarea_queue_winredraw(curarea);
1449 }
1450
1451 int minmax_tface_uv(float *min, float *max)
1452 {
1453         EditMesh *em= G.editMesh;
1454         EditFace *efa;
1455         MTFace *tf;
1456         int sel;
1457         
1458         if( is_uv_tface_editing_allowed()==0 ) return 0;
1459
1460         INIT_MINMAX2(min, max);
1461
1462         sel= 0;
1463         for (efa= em->faces.first; efa; efa= efa->next) {
1464                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1465                 if (SIMA_FACEDRAW_CHECK(efa, tf)) {
1466                         if (SIMA_UVSEL_CHECK(efa, tf, 0))                               DO_MINMAX2(tf->uv[0], min, max);
1467                         if (SIMA_UVSEL_CHECK(efa, tf, 1))                               DO_MINMAX2(tf->uv[1], min, max);
1468                         if (SIMA_UVSEL_CHECK(efa, tf, 2))                               DO_MINMAX2(tf->uv[2], min, max);
1469                         if (efa->v4 && (SIMA_UVSEL_CHECK(efa, tf, 3)))  DO_MINMAX2(tf->uv[3], min, max);
1470                         sel = 1;
1471                 }
1472         }
1473         return sel;
1474 }
1475
1476 int cent_tface_uv(float *cent, int mode)
1477 {
1478         float min[2], max[2];
1479         short change= 0;
1480         
1481         if (mode==0) {
1482                 if (minmax_tface_uv(min, max))
1483                         change = 1;
1484
1485         } else if (mode==1) {
1486                 EditFace *efa;
1487                 MTFace *tf;
1488                 INIT_MINMAX2(min, max);
1489                 
1490                 for (efa= G.editMesh->faces.first; efa; efa= efa->next) {
1491                         tf = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
1492                         if (SIMA_FACEDRAW_CHECK(efa, tf)) {
1493                                 if (SIMA_UVSEL_CHECK(efa, tf, 0))                               { DO_MINMAX2(tf->uv[0], min, max);      change= 1;}
1494                                 if (SIMA_UVSEL_CHECK(efa, tf, 1))                               { DO_MINMAX2(tf->uv[1], min, max);      change= 1;}
1495                                 if (SIMA_UVSEL_CHECK(efa, tf, 2))                               { DO_MINMAX2(tf->uv[2], min, max);      change= 1;}
1496                                 if (efa->v4 && (SIMA_UVSEL_CHECK(efa, tf, 3)))  { DO_MINMAX2(tf->uv[3], min, max);      change= 1;}
1497                         }
1498                 }
1499         }
1500         
1501         if (change) {
1502                 cent[0]= (min[0]+max[0])/2.0;
1503                 cent[1]= (min[1]+max[1])/2.0;
1504                 return 1;
1505         }
1506         return 0;
1507 }
1508
1509 static void sima_show_info(int channels, int x, int y, char *cp, float *fp, int *zp, float *zpf)
1510 {
1511         short ofs;
1512         char str[256];
1513         
1514         ofs= sprintf(str, "X: %d Y: %d ", x, y);
1515         if(cp)
1516                 ofs+= sprintf(str+ofs, "| R: %d G: %d B: %d A: %d ", cp[0], cp[1], cp[2], cp[3]);
1517         if(fp) {
1518                 if(channels==4)
1519                         ofs+= sprintf(str+ofs, "| R: %.3f G: %.3f B: %.3f A: %.3f ", fp[0], fp[1], fp[2], fp[3]);
1520                 else if(channels==1)
1521                         ofs+= sprintf(str+ofs, "| Val: %.3f ", fp[0]);
1522                 else if(channels==3)
1523                         ofs+= sprintf(str+ofs, "| R: %.3f G: %.3f B: %.3f ", fp[0], fp[1], fp[2]);
1524         }
1525         if(zp)
1526                 ofs+= sprintf(str+ofs, "| Z: %.4f ", 0.5+0.5*( ((float)*zp)/(float)0x7fffffff));
1527         if(zpf)
1528                 ofs+= sprintf(str+ofs, "| Z: %.3f ", *zpf);
1529         
1530         glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
1531         glEnable(GL_BLEND);
1532         
1533         glColor4f(.0,.0,.0,.25);
1534         glRectf(0.0, 0.0, curarea->winx, 30.0);
1535         glDisable(GL_BLEND);
1536         
1537         glColor3ub(255, 255, 255);
1538         glRasterPos2i(10, 10);
1539         
1540         BMF_DrawString(G.fonts, str);
1541
1542 }
1543
1544 void sima_sample_color(void)
1545 {
1546         ImBuf *ibuf= BKE_image_get_ibuf(G.sima->image, &G.sima->iuser);
1547         float fx, fy;
1548         short mval[2], mvalo[2], firsttime=1;
1549         
1550         if(ibuf==NULL)
1551                 return;
1552         
1553         calc_image_view(G.sima, 'f');
1554         getmouseco_areawin(mvalo);
1555         
1556         while(get_mbut() & L_MOUSE) {
1557                 
1558                 getmouseco_areawin(mval);
1559                 if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || firsttime) {
1560                         firsttime= 0;
1561                         areamouseco_to_ipoco(G.v2d, mval, &fx, &fy);
1562                         
1563                         if(fx>=0.0 && fy>=0.0 && fx<1.0 && fy<1.0) {
1564                                 float *fp= NULL, *zpf= NULL;
1565                                 int *zp= NULL;
1566                                 char *cp= NULL;
1567                                 
1568                                 int x= (int) (fx*ibuf->x);
1569                                 int y= (int) (fy*ibuf->y);
1570                                 
1571                                 if(x>=ibuf->x) x= ibuf->x-1;
1572                                 if(y>=ibuf->y) y= ibuf->y-1;
1573                                 
1574                                 if(ibuf->rect)
1575                                         cp= (char *)(ibuf->rect + y*ibuf->x + x);
1576                                 if(ibuf->zbuf)
1577                                         zp= ibuf->zbuf + y*ibuf->x + x;
1578                                 if(ibuf->zbuf_float)
1579                                         zpf= ibuf->zbuf_float + y*ibuf->x + x;
1580                                 if(ibuf->rect_float)
1581                                         fp= (ibuf->rect_float + (ibuf->channels)*(y*ibuf->x + x));
1582                                         
1583                                 if(G.sima->cumap) {
1584                                         float vec[3];
1585                                         if(fp==NULL) {
1586                                                 fp= vec;
1587                                                 vec[0]= (float)cp[0]/255.0f;
1588                                                 vec[1]= (float)cp[1]/255.0f;
1589                                                 vec[2]= (float)cp[2]/255.0f;
1590                                         }
1591                                         
1592                                         if(ibuf->channels==4) {
1593                                                 if(G.qual & LR_CTRLKEY) {
1594                                                         curvemapping_set_black_white(G.sima->cumap, NULL, fp);
1595                                                         curvemapping_do_ibuf(G.sima->cumap, ibuf);
1596                                                 }
1597                                                 else if(G.qual & LR_SHIFTKEY) {
1598                                                         curvemapping_set_black_white(G.sima->cumap, fp, NULL);
1599                                                         curvemapping_do_ibuf(G.sima->cumap, ibuf);
1600                                                 }
1601                                         }
1602                                 }
1603                                 
1604                                 scrarea_do_windraw(curarea);
1605                                 myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
1606                                 glLoadIdentity();
1607                                 sima_show_info(ibuf->channels, x, y, cp, fp, zp, zpf);
1608                                 screen_swapbuffers();
1609                         }
1610                         
1611                 }
1612                 BIF_wait_for_statechange();
1613         }
1614         
1615         scrarea_queue_winredraw(curarea);
1616 }
1617
1618 /* Image functions */
1619
1620 static void load_image_filesel(char *str)       /* called from fileselect */
1621 {
1622         Image *ima= NULL;
1623
1624         ima= BKE_add_image_file(str);
1625         if(ima) {
1626                 BKE_image_signal(ima, &G.sima->iuser, IMA_SIGNAL_RELOAD);
1627                 image_changed(G.sima, ima);
1628         }
1629         BIF_undo_push("Load image UV");
1630         allqueue(REDRAWIMAGE, 0);
1631 }
1632
1633 static void replace_image_filesel(char *str)            /* called from fileselect */
1634 {
1635         if (!G.sima->image)
1636                 return;
1637         
1638         strncpy(G.sima->image->name, str, sizeof(G.sima->image->name)-1); /* we cant do much if the str is longer then 240 :/ */
1639         BKE_image_signal(G.sima->image, &G.sima->iuser, IMA_SIGNAL_RELOAD);
1640         BIF_undo_push("Replace image UV");
1641         allqueue(REDRAWIMAGE, 0);
1642         allqueue(REDRAWVIEW3D, 0);
1643 }
1644
1645
1646 static void save_image_doit(char *name)
1647 {
1648         Image *ima= G.sima->image;
1649         ImBuf *ibuf= BKE_image_get_ibuf(ima, &G.sima->iuser);
1650         int len;
1651         char str[FILE_MAXDIR+FILE_MAXFILE];
1652
1653         if (ibuf) {
1654                 BLI_strncpy(str, name, sizeof(str));
1655
1656                 BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
1657                 
1658                 if(G.scene->r.scemode & R_EXTENSION) 
1659                         BKE_add_image_extension(str, G.sima->imtypenr);
1660                 
1661                 if (saveover(str)) {
1662                         
1663                         /* enforce user setting for RGB or RGBA, but skip BW */
1664                         if(G.scene->r.planes==32)
1665                                 ibuf->depth= 32;
1666                         else if(G.scene->r.planes==24)
1667                                 ibuf->depth= 24;
1668                         
1669                         waitcursor(1);
1670                         if(G.sima->imtypenr==R_MULTILAYER) {
1671                                 RenderResult *rr= BKE_image_get_renderresult(ima);
1672                                 if(rr) {
1673                                         RE_WriteRenderResult(rr, str, G.scene->r.quality);
1674                                         
1675                                         BLI_strncpy(ima->name, name, sizeof(ima->name));
1676                                         BLI_strncpy(ibuf->name, str, sizeof(ibuf->name));
1677                                         
1678                                         /* should be function? nevertheless, saving only happens here */
1679                                         for(ibuf= ima->ibufs.first; ibuf; ibuf= ibuf->next)
1680                                                 ibuf->userflags &= ~IB_BITMAPDIRTY;
1681                                         
1682                                 }
1683                                 else error("Did not write, no Multilayer Image");
1684                         }
1685                         else if (BKE_write_ibuf(ibuf, str, G.sima->imtypenr, G.scene->r.subimtype, G.scene->r.quality)) {
1686                                 BLI_strncpy(ima->name, name, sizeof(ima->name));
1687                                 BLI_strncpy(ibuf->name, str, sizeof(ibuf->name));
1688                                 
1689                                 ibuf->userflags &= ~IB_BITMAPDIRTY;
1690                                 
1691                                 /* change type? */
1692                                 if( ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC_VIEWER)) {
1693                                         ima->source= IMA_SRC_FILE;
1694                                         ima->type= IMA_TYPE_IMAGE;
1695                                 }
1696                                 if(ima->type==IMA_TYPE_R_RESULT)
1697                                         ima->type= IMA_TYPE_IMAGE;
1698                                 
1699                                 /* name image as how we saved it */
1700                                 len= strlen(str);
1701                                 while (len > 0 && str[len - 1] != '/' && str[len - 1] != '\\') len--;
1702                                 rename_id(&ima->id, str+len);
1703                         } 
1704                         else {
1705                                 error("Couldn't write image: %s", str);
1706                         }
1707
1708                         allqueue(REDRAWHEADERS, 0);
1709                         allqueue(REDRAWBUTSSHADING, 0);
1710
1711                         waitcursor(0);
1712                 }
1713         }
1714 }
1715
1716 void open_image_sima(short imageselect)
1717 {
1718         char name[FILE_MAXDIR+FILE_MAXFILE];
1719
1720         if(G.sima->image)
1721                 strcpy(name, G.sima->image->name);
1722         else
1723                 strcpy(name, U.textudir);
1724
1725         if(imageselect)
1726                 activate_imageselect(FILE_SPECIAL, "Open Image", name, load_image_filesel);
1727         else
1728                 activate_fileselect(FILE_SPECIAL, "Open Image", name, load_image_filesel);
1729 }
1730
1731 void replace_image_sima(short imageselect)
1732 {
1733         char name[FILE_MAXDIR+FILE_MAXFILE];
1734
1735         if(G.sima->image)
1736                 strcpy(name, G.sima->image->name);
1737         else
1738                 strcpy(name, U.textudir);
1739         
1740         if(imageselect)
1741                 activate_imageselect(FILE_SPECIAL, "Replace Image", name, replace_image_filesel);
1742         else
1743                 activate_fileselect(FILE_SPECIAL, "Replace Image", name, replace_image_filesel);
1744 }
1745
1746
1747 static char *filesel_imagetype_string(Image *ima)
1748 {
1749         char *strp, *str= MEM_callocN(14*32, "menu for filesel");
1750         
1751         strp= str;
1752         str += sprintf(str, "Save Image as: %%t|");
1753         str += sprintf(str, "Targa %%x%d|", R_TARGA);
1754         str += sprintf(str, "Targa Raw %%x%d|", R_RAWTGA);
1755         str += sprintf(str, "PNG %%x%d|", R_PNG);
1756         str += sprintf(str, "BMP %%x%d|", R_BMP);
1757         str += sprintf(str, "Jpeg %%x%d|", R_JPEG90);
1758         str += sprintf(str, "Iris %%x%d|", R_IRIS);
1759         if(G.have_libtiff)
1760                 str += sprintf(str, "Tiff %%x%d|", R_TIFF);
1761         str += sprintf(str, "Radiance HDR %%x%d|", R_RADHDR);
1762         str += sprintf(str, "Cineon %%x%d|", R_CINEON);
1763         str += sprintf(str, "DPX %%x%d|", R_DPX);
1764 #ifdef WITH_OPENEXR
1765         str += sprintf(str, "OpenEXR %%x%d|", R_OPENEXR);
1766         /* saving sequences of multilayer won't work, they copy buffers  */
1767         if(ima->source==IMA_SRC_SEQUENCE && ima->type==IMA_TYPE_MULTILAYER);
1768         else str += sprintf(str, "MultiLayer %%x%d|", R_MULTILAYER);
1769 #endif  
1770         return strp;
1771 }
1772
1773 /* always opens fileselect */
1774 void save_as_image_sima(void)
1775 {
1776         Image *ima = G.sima->image;
1777         ImBuf *ibuf= BKE_image_get_ibuf(ima, &G.sima->iuser);
1778         char name[FILE_MAXDIR+FILE_MAXFILE];
1779
1780         if (ima) {
1781                 strcpy(name, ima->name);
1782
1783                 if (ibuf) {
1784                         char *strp;
1785                         
1786                         strp= filesel_imagetype_string(ima);
1787                         
1788                         /* cant save multilayer sequence, ima->rr isn't valid for a specific frame */
1789                         if(ima->rr && !(ima->source==IMA_SRC_SEQUENCE && ima->type==IMA_TYPE_MULTILAYER))
1790                                 G.sima->imtypenr= R_MULTILAYER;
1791                         else if(ima->type==IMA_TYPE_R_RESULT)
1792                                 G.sima->imtypenr= G.scene->r.imtype;
1793                         else G.sima->imtypenr= BKE_ftype_to_imtype(ibuf->ftype);
1794                         
1795                         activate_fileselect_menu(FILE_SPECIAL, "Save Image", name, strp, &G.sima->imtypenr, save_image_doit);
1796                 }
1797         }
1798 }
1799
1800 /* if exists, saves over without fileselect */
1801 void save_image_sima(void)
1802 {
1803         Image *ima = G.sima->image;
1804         ImBuf *ibuf= BKE_image_get_ibuf(ima, &G.sima->iuser);
1805         char name[FILE_MAXDIR+FILE_MAXFILE];
1806
1807         if (ima) {
1808                 strcpy(name, ima->name);
1809
1810                 if (ibuf) {
1811                         if (BLI_exists(ibuf->name)) {
1812                                 if(BKE_image_get_renderresult(ima)) 
1813                                         G.sima->imtypenr= R_MULTILAYER;
1814                                 else 
1815                                         G.sima->imtypenr= BKE_ftype_to_imtype(ibuf->ftype);
1816                                 
1817                                 save_image_doit(ibuf->name);
1818                         }
1819                         else
1820                                 save_as_image_sima();
1821                 }
1822         }
1823 }
1824
1825 void save_image_sequence_sima(void)
1826 {
1827         ImBuf *ibuf;
1828         int tot= 0;
1829         char di[FILE_MAX], fi[FILE_MAX];
1830         
1831         if(G.sima->image==NULL)
1832                 return;
1833         if(G.sima->image->source!=IMA_SRC_SEQUENCE)
1834                 return;
1835         if(G.sima->image->type==IMA_TYPE_MULTILAYER) {
1836                 error("Cannot save Multilayer Sequences");
1837                 return;
1838         }
1839         
1840         /* get total */
1841         for(ibuf= G.sima->image->ibufs.first; ibuf; ibuf= ibuf->next) 
1842                 if(ibuf->userflags & IB_BITMAPDIRTY)
1843                         tot++;
1844         
1845         if(tot==0) {
1846                 notice("No Images have been changed");
1847                 return;
1848         }
1849         /* get a filename for menu */
1850         for(ibuf= G.sima->image->ibufs.first; ibuf; ibuf= ibuf->next) 
1851                 if(ibuf->userflags & IB_BITMAPDIRTY)
1852                         break;
1853         
1854         BLI_strncpy(di, ibuf->name, FILE_MAX);
1855         BLI_splitdirstring(di, fi);
1856         
1857         sprintf(fi, "%d Image(s) will be saved in %s", tot, di);
1858         if(okee(fi)) {
1859                 
1860                 for(ibuf= G.sima->image->ibufs.first; ibuf; ibuf= ibuf->next) {
1861                         if(ibuf->userflags & IB_BITMAPDIRTY) {
1862                                 char name[FILE_MAX];
1863                                 BLI_strncpy(name, ibuf->name, sizeof(name));
1864                                 
1865                                 BLI_convertstringcode(name, G.sce, 0);
1866
1867                                 if(0 == IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat)) {
1868                                         error("Could not write image", name);
1869                                         break;
1870                                 }
1871                                 printf("Saved: %s\n", ibuf->name);
1872                                 ibuf->userflags &= ~IB_BITMAPDIRTY;
1873                         }
1874                 }
1875         }
1876 }
1877
1878 void reload_image_sima(void)
1879 {
1880         if (G.sima ) {
1881                 BKE_image_signal(G.sima->image, &G.sima->iuser, IMA_SIGNAL_RELOAD);
1882                 /* image_changed(G.sima, 0); - do we really need this? */
1883         }
1884
1885         allqueue(REDRAWIMAGE, 0);
1886         allqueue(REDRAWVIEW3D, 0);
1887         BIF_preview_changed(ID_TE);
1888 }
1889
1890 void new_image_sima(void)
1891 {
1892         static int width= 256, height= 256;
1893         static short uvtestgrid= 0;
1894         static float color[] = {0, 0, 0, 1};
1895         char name[22];
1896         Image *ima;
1897         
1898         strcpy(name, "Untitled");
1899
1900         add_numbut(0, TEX, "Name:", 0, 21, name, NULL);
1901         add_numbut(1, NUM|INT, "Width:", 1, 5000, &width, NULL);
1902         add_numbut(2, NUM|INT, "Height:", 1, 5000, &height, NULL);
1903         add_numbut(3, COL, "", 0, 0, &color, NULL);
1904         add_numbut(4, NUM|FLO, "Alpha:", 0.0, 1.0, &color[3], NULL);
1905         add_numbut(5, TOG|SHO, "UV Test Grid", 0, 0, &uvtestgrid, NULL);
1906         if (!do_clever_numbuts("New Image", 6, REDRAW))
1907                 return;
1908
1909         ima = BKE_add_image_size(width, height, name, uvtestgrid, color);
1910         image_changed(G.sima, ima);
1911         BKE_image_signal(G.sima->image, &G.sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE);
1912         BIF_undo_push("Add image");
1913
1914         allqueue(REDRAWIMAGE, 0);
1915         allqueue(REDRAWVIEW3D, 0);
1916 }
1917
1918 void pack_image_sima()
1919 {
1920         Image *ima = G.sima->image;
1921
1922         if (ima) {
1923                 if(ima->source!=IMA_SRC_SEQUENCE && ima->source!=IMA_SRC_MOVIE) {
1924                         if (ima->packedfile) {
1925                                 if (G.fileflags & G_AUTOPACK)
1926                                         if (okee("Disable AutoPack?"))
1927                                                 G.fileflags &= ~G_AUTOPACK;
1928                                 
1929                                 if ((G.fileflags & G_AUTOPACK) == 0) {
1930                                         unpackImage(ima, PF_ASK);
1931                                         BIF_undo_push("Unpack image");
1932                                 }
1933                         }
1934                         else {
1935                                 ImBuf *ibuf= BKE_image_get_ibuf(ima, &G.sima->iuser);
1936                                 if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) {
1937                                         if(okee("Can't pack painted image. Use Repack as PNG?"))
1938                                                 BKE_image_memorypack(ima);
1939                                 }
1940                                 else {
1941                                         ima->packedfile = newPackedFile(ima->name);
1942                                         BIF_undo_push("Pack image");
1943                                 }
1944                         }
1945
1946                         allqueue(REDRAWBUTSSHADING, 0);
1947                         allqueue(REDRAWHEADERS, 0);
1948                 }
1949         }
1950 }
1951
1952
1953
1954 /* goes over all ImageUsers, and sets frame numbers if auto-refresh is set */
1955 void BIF_image_update_frame(void)
1956 {
1957         Tex *tex;
1958         
1959         /* texture users */
1960         for(tex= G.main->tex.first; tex; tex= tex->id.next) {
1961                 if(tex->type==TEX_IMAGE && tex->ima)
1962                         if(ELEM(tex->ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE))
1963                                 if(tex->iuser.flag & IMA_ANIM_ALWAYS)
1964                                         BKE_image_user_calc_imanr(&tex->iuser, G.scene->r.cfra, 0);
1965                 
1966         }
1967         /* image window, compo node users */
1968         if(G.curscreen) {
1969                 ScrArea *sa;
1970                 for(sa= G.curscreen->areabase.first; sa; sa= sa->next) {
1971                         if(sa->spacetype==SPACE_VIEW3D) {
1972                                 View3D *v3d= sa->spacedata.first;
1973                                 if(v3d->bgpic)
1974                                         if(v3d->bgpic->iuser.flag & IMA_ANIM_ALWAYS)
1975                                                 BKE_image_user_calc_imanr(&v3d->bgpic->iuser, G.scene->r.cfra, 0);
1976                         }
1977                         else if(sa->spacetype==SPACE_IMAGE) {
1978                                 SpaceImage *sima= sa->spacedata.first;
1979                                 if(sima->iuser.flag & IMA_ANIM_ALWAYS)
1980                                         BKE_image_user_calc_imanr(&sima->iuser, G.scene->r.cfra, 0);
1981                         }
1982                         else if(sa->spacetype==SPACE_NODE) {
1983                                 SpaceNode *snode= sa->spacedata.first;
1984                                 if((snode->treetype==NTREE_COMPOSIT) && (snode->nodetree)) {
1985                                         bNode *node;
1986                                         for(node= snode->nodetree->nodes.first; node; node= node->next) {
1987                                                 if(node->id && node->type==CMP_NODE_IMAGE) {
1988                                                         Image *ima= (Image *)node->id;
1989                                                         ImageUser *iuser= node->storage;
1990                                                         if(ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE))
1991                                                                 if(iuser->flag & IMA_ANIM_ALWAYS)
1992                                                                         BKE_image_user_calc_imanr(iuser, G.scene->r.cfra, 0);
1993                                                 }
1994                                         }
1995                                 }
1996                         }
1997                 }
1998         }
1999 }
2000
2001 void aspect_sima(SpaceImage *sima, float *x, float *y)
2002 {
2003         *x = *y = 1.0;
2004         
2005         if(             (sima->image == 0) ||
2006                         (sima->image->type == IMA_TYPE_R_RESULT) ||
2007                         (sima->image->type == IMA_TYPE_COMPOSITE) ||
2008                         (sima->image->tpageflag & IMA_TILES) ||
2009                         (sima->image->aspx==0.0 || sima->image->aspy==0.0)
2010         ) {
2011                 return;
2012         }
2013         
2014         /* x is always 1 */
2015         *y = sima->image->aspy / sima->image->aspx;
2016 }