4a748e4e4df9bc8436b6a5f9fa58967c00415bb9
[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, sticky, actface, nearestuv, i;
535         short flush = 0; /* 0 == dont flush, 1 == sel, -1 == desel;  only use when selection sync is enabled */
536         unsigned int hitv[4], nearestv;
537         float *hituv[4], limit[2];
538         
539         if( is_uv_tface_editing_allowed()==0 ) return;
540
541         get_connected_limit_tface_uv(limit);
542         
543         if (G.sima->flag & SI_SYNC_UVSEL) {
544                 /* copy from mesh */
545                 if (G.scene->selectmode == SCE_SELECT_FACE) {
546                         actface= 1;
547                         sticky= 0;
548                 } else {
549                         actface= (G.qual & LR_ALTKEY || G.sima->flag & SI_SELACTFACE);
550                         sticky= 2;
551                 }
552         } else {
553                 /* normal operation */
554                 actface= (G.qual & LR_ALTKEY || G.sima->flag & SI_SELACTFACE);
555                 
556                 if(G.qual & LR_CTRLKEY) {
557                         if(G.sima->flag & SI_STICKYUVS) sticky= 0;
558                         else sticky= 1;
559                 }
560                 else {
561                         if(G.sima->flag & SI_STICKYUVS) sticky= 1;
562                         else if(G.sima->flag & SI_LOCALSTICKY) sticky= 2;
563                         else sticky= 0;
564                 }
565         }
566
567         if(actface) {
568                 find_nearest_tface(&nearesttf, &nearestefa);
569                 if(nearesttf==NULL)
570                         return;
571
572                 nearesttf->flag |= TF_ACTIVE;
573
574                 for (i=0; i<4; i++)
575                         hituv[i]= nearesttf->uv[i];
576
577                 hitv[0]= nearestefa->v1->tmp.l;
578                 hitv[1]= nearestefa->v2->tmp.l;
579                 hitv[2]= nearestefa->v3->tmp.l;
580                 
581                 if (nearestefa->v4)     hitv[3]= nearestefa->v4->tmp.l;
582                 else                            hitv[3]= 0xFFFFFFFF;
583         }
584         else {
585                 find_nearest_uv(&nearesttf, &nearestefa, &nearestv, &nearestuv);
586                 if(nearesttf==NULL)
587                         return;
588
589                 if(sticky) {
590                         for(i=0; i<4; i++)
591                                 hitv[i]= 0xFFFFFFFF;
592                         hitv[nearestuv]= nearestv;
593                         hituv[nearestuv]= nearesttf->uv[nearestuv];
594                 }
595         }
596
597         if(G.qual & LR_SHIFTKEY) {
598                 /* (de)select face */
599                 if(actface) {
600                         if(SIMA_FACESEL_CHECK(nearestefa, nearesttf)) {
601                                 SIMA_FACESEL_UNSET(nearestefa, nearesttf);
602                                 selectsticky= 0;
603                         }
604                         else {
605                                 SIMA_FACESEL_SET(nearestefa, nearesttf);
606                                 selectsticky= 1;
607                         }
608                         flush = -1;
609                 }
610                 /* (de)select uv node */
611                 else {
612                         if (SIMA_UVSEL_CHECK(nearestefa, nearesttf, nearestuv)) {
613                                 SIMA_UVSEL_UNSET(nearestefa, nearesttf, nearestuv);
614                                 selectsticky= 0;
615                         }
616                         else {
617                                 SIMA_UVSEL_SET(nearestefa, nearesttf, nearestuv);
618                                 selectsticky= 1;
619                         }
620                         flush = 1;
621                 }
622
623                 /* (de)select sticky uv nodes */
624                 if(sticky || actface) {
625                         EditVert *ev;
626                         
627                         for (a=0, ev=em->verts.first; ev; ev = ev->next, a++)
628                                 ev->tmp.l = a;
629                         
630                         /* deselect */
631                         if(selectsticky==0) {
632                                 for (efa= em->faces.first; efa; efa= efa->next) {
633                                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
634                                         if (SIMA_FACEDRAW_CHECK(efa, tf)) {
635                                                 /*if(nearesttf && tf!=nearesttf) tf->flag &=~ TF_ACTIVE;*/ /* TODO - deal with editmesh active face */
636                                                 if (!sticky) continue;
637         
638                                                 if(msel_hit(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
639                                                         SIMA_UVSEL_UNSET(efa, tf, 0);
640                                                 if(msel_hit(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
641                                                         SIMA_UVSEL_UNSET(efa, tf, 1);
642                                                 if(msel_hit(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
643                                                         SIMA_UVSEL_UNSET(efa, tf, 2);
644                                                 if (efa->v4)
645                                                         if(msel_hit(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
646                                                                 SIMA_UVSEL_UNSET(efa, tf, 3);
647                                         }
648                                 }
649                                 flush = -1;
650                         }
651                         /* select */
652                         else {
653                                 for (efa= em->faces.first; efa; efa= efa->next) {
654                                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
655                                         if (SIMA_FACEDRAW_CHECK(efa, tf)) {
656                                                 if(nearesttf && tf!=nearesttf)
657                                                         tf->flag &=~ TF_ACTIVE;
658                                                 if (!sticky) continue;
659         
660                                                 if(msel_hit(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
661                                                         SIMA_UVSEL_SET(efa, tf, 0);
662                                                 if(msel_hit(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
663                                                         SIMA_UVSEL_SET(efa, tf, 1);
664                                                 if(msel_hit(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
665                                                         SIMA_UVSEL_SET(efa, tf, 2);
666                                                 if (efa->v4)
667                                                         if(msel_hit(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
668                                                                 SIMA_UVSEL_SET(efa, tf, 3);
669                                         }
670                                 }
671                                 flush = 1;
672                         }                       
673                 }
674         }
675         else {
676                 /* select face and deselect other faces */ 
677                 if(actface) {
678                         for (efa= em->faces.first; efa; efa= efa->next) {
679                                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
680                                 SIMA_FACESEL_UNSET(efa, tf);
681                                 //if(nearesttf && tf!=nearesttf) /* TODO - deal with editmesh active face */
682                                 //      tf->flag &= ~TF_ACTIVE;
683                         }
684                         if(nearesttf)
685                                 SIMA_FACESEL_SET(nearestefa, nearesttf);
686                 }
687
688                 /* deselect uvs, and select sticky uvs */
689                 for (efa= em->faces.first; efa; efa= efa->next) {
690                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
691                         if (SIMA_FACEDRAW_CHECK(efa, tf)) {
692                                 if(!actface) SIMA_FACESEL_UNSET(efa, tf);
693                                 if(!sticky) continue;
694
695                                 if(msel_hit(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
696                                         SIMA_UVSEL_SET(efa, tf, 0);
697                                 if(msel_hit(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
698                                         SIMA_UVSEL_SET(efa, tf, 1);
699                                 if(msel_hit(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
700                                         SIMA_UVSEL_SET(efa, tf, 2);
701                                 if(efa->v4)
702                                         if(msel_hit(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
703                                                 SIMA_UVSEL_SET(efa, tf, 3);
704                                 flush= 1;
705                         }
706                 }
707                 
708                 if(!actface) {
709                         SIMA_UVSEL_SET(nearestefa, nearesttf, nearestuv);
710                         flush= 1;
711                 }
712         }
713         
714         force_draw(1);
715         
716         if (G.sima->flag & SI_SYNC_UVSEL) {
717                 /* flush for mesh selection */
718                 if (G.scene->selectmode != SCE_SELECT_FACE) {
719                         if (flush==1)           EM_select_flush();
720                         else if (flush==-1)     EM_deselect_flush();
721                 }
722                 allqueue(REDRAWVIEW3D, 0); /* mesh selection has changed */
723         }
724         
725         BIF_undo_push("Select UV");
726         rightmouse_transform();
727 }
728
729 void borderselect_sima(short whichuvs)
730 {
731         EditMesh *em = G.editMesh;
732         EditFace *efa;
733         MTFace *tface;
734         rcti rect;
735         rctf rectf;
736         int val;
737         short mval[2];
738
739         if( is_uv_tface_editing_allowed()==0) return;
740
741         val= get_border(&rect, 3);
742
743         if(val) {
744                 mval[0]= rect.xmin;
745                 mval[1]= rect.ymin;
746                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
747                 mval[0]= rect.xmax;
748                 mval[1]= rect.ymax;
749                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
750
751                 for (efa= em->faces.first; efa; efa= efa->next) {
752                         tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
753                         if (SIMA_FACEDRAW_CHECK(efa, tface)) {
754                                 if (whichuvs == UV_SELECT_ALL || (G.sima->flag & SI_SYNC_UVSEL) ) {
755                                         /* SI_SYNC_UVSEL - cant do pinned selection */
756                                         if(BLI_in_rctf(&rectf, (float)tface->uv[0][0], (float)tface->uv[0][1])) {
757                                                 if(val==LEFTMOUSE)      SIMA_UVSEL_SET(efa, tface, 0);
758                                                 else                            SIMA_UVSEL_UNSET(efa, tface, 0);
759                                         }
760                                         if(BLI_in_rctf(&rectf, (float)tface->uv[1][0], (float)tface->uv[1][1])) {
761                                                 if(val==LEFTMOUSE)      SIMA_UVSEL_SET(efa, tface, 1);
762                                                 else                            SIMA_UVSEL_UNSET(efa, tface, 1);
763                                         }
764                                         if(BLI_in_rctf(&rectf, (float)tface->uv[2][0], (float)tface->uv[2][1])) {
765                                                 if(val==LEFTMOUSE)      SIMA_UVSEL_SET(efa, tface, 2);
766                                                 else                            SIMA_UVSEL_UNSET(efa, tface, 2);
767                                         }
768                                         if(efa->v4 && BLI_in_rctf(&rectf, (float)tface->uv[3][0], (float)tface->uv[3][1])) {
769                                                 if(val==LEFTMOUSE)      SIMA_UVSEL_SET(efa, tface, 3);
770                                                 else                            SIMA_UVSEL_UNSET(efa, tface, 3);
771                                         }
772                                 } else if (whichuvs == UV_SELECT_PINNED) {
773                                         if ((tface->unwrap & TF_PIN1) && 
774                                                 BLI_in_rctf(&rectf, (float)tface->uv[0][0], (float)tface->uv[0][1])) {
775                                                 
776                                                 if(val==LEFTMOUSE)      SIMA_UVSEL_SET(efa, tface, 0);
777                                                 else                            SIMA_UVSEL_UNSET(efa, tface, 0);
778                                         }
779                                         if ((tface->unwrap & TF_PIN2) && 
780                                                 BLI_in_rctf(&rectf, (float)tface->uv[1][0], (float)tface->uv[1][1])) {
781                                                 
782                                                 if(val==LEFTMOUSE)      SIMA_UVSEL_SET(efa, tface, 1);
783                                                 else                            SIMA_UVSEL_UNSET(efa, tface, 1);
784                                         }
785                                         if ((tface->unwrap & TF_PIN3) && 
786                                                 BLI_in_rctf(&rectf, (float)tface->uv[2][0], (float)tface->uv[2][1])) {
787                                                 
788                                                 if(val==LEFTMOUSE)      SIMA_UVSEL_SET(efa, tface, 2);
789                                                 else                            SIMA_UVSEL_UNSET(efa, tface, 2);
790                                         }
791                                         if ((efa->v4) && (tface->unwrap & TF_PIN4) && BLI_in_rctf(&rectf, (float)tface->uv[3][0], (float)tface->uv[3][1])) {
792                                                 if(val==LEFTMOUSE)      SIMA_UVSEL_SET(efa, tface, 3);
793                                                 else                            SIMA_UVSEL_UNSET(efa, tface, 3);
794                                         }
795                                 }
796                         }
797                 }
798                 
799                 /* make sure newly selected vert selection is updated*/
800                 if (G.sima->flag & SI_SYNC_UVSEL) {
801                         if (G.scene->selectmode != SCE_SELECT_FACE) {
802                                 if (val==LEFTMOUSE)     EM_select_flush();
803                                 else                            EM_deselect_flush();
804                         }
805                         allqueue(REDRAWVIEW3D, 0); /* mesh selection has changed */
806                 }
807                 
808                 BIF_undo_push("Border select UV");
809                 scrarea_queue_winredraw(curarea);
810         }
811 }
812
813 int snap_uv_sel_to_curs(void)
814 {
815         EditMesh *em = G.editMesh;
816         EditFace *efa;
817         MTFace *tface;
818         short change = 0;
819
820         for (efa= em->faces.first; efa; efa= efa->next) {
821                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
822                 if (SIMA_FACEDRAW_CHECK(efa, tface)) {
823                         if (SIMA_UVSEL_CHECK(efa, tface, 0))            VECCOPY2D(tface->uv[0], G.v2d->cursor);
824                         if (SIMA_UVSEL_CHECK(efa, tface, 1))            VECCOPY2D(tface->uv[1], G.v2d->cursor);
825                         if (SIMA_UVSEL_CHECK(efa, tface, 2))            VECCOPY2D(tface->uv[2], G.v2d->cursor);
826                         if (efa->v4)
827                                 if (SIMA_UVSEL_CHECK(efa, tface, 3))    VECCOPY2D(tface->uv[3], G.v2d->cursor);
828                         change = 1;
829                 }
830         }
831         return change;
832 }
833
834 void snap_coord_to_pixel(float *uvco, float w, float h)
835 {
836         uvco[0] = ((float) ((int)((uvco[0]*w) + 0.5))) / w;  
837         uvco[1] = ((float) ((int)((uvco[1]*h) + 0.5))) / h;  
838 }
839
840 int snap_uv_sel_to_pixels(void) /* warning, sanity checks must alredy be done */
841 {
842         EditMesh *em = G.editMesh;
843         EditFace *efa;
844         MTFace *tface;
845         int wi, hi;
846         float w, h;
847         short change = 0;
848
849         transform_width_height_tface_uv(&wi, &hi);
850         w = (float)wi;
851         h = (float)hi;
852         
853         for (efa= em->faces.first; efa; efa= efa->next) {
854                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
855                 if (SIMA_FACEDRAW_CHECK(efa, tface)) {
856                         if (SIMA_UVSEL_CHECK(efa, tface, 0)) snap_coord_to_pixel(tface->uv[0], w, h);
857                         if (SIMA_UVSEL_CHECK(efa, tface, 1)) snap_coord_to_pixel(tface->uv[1], w, h);
858                         if (SIMA_UVSEL_CHECK(efa, tface, 2)) snap_coord_to_pixel(tface->uv[2], w, h);
859                         if (efa->v4)
860                                 if (SIMA_UVSEL_CHECK(efa, tface, 3)) snap_coord_to_pixel(tface->uv[3], w, h);
861                         change = 1;
862                 }
863         }
864         return change;
865 }
866
867 void snap_uv_curs_to_pixels(void)
868 {
869         int wi, hi;
870         float w, h;
871
872         transform_width_height_tface_uv(&wi, &hi);
873         w = (float)wi;
874         h = (float)hi;
875         snap_coord_to_pixel(G.v2d->cursor, w, h);
876 }
877
878 int snap_uv_curs_to_sel(void)
879 {
880         if( is_uv_tface_editing_allowed()==0 ) return 0;
881         return cent_tface_uv(G.v2d->cursor, 0);
882 }
883
884 void snap_menu_sima(void)
885 {
886         short event;
887         if( is_uv_tface_editing_allowed()==0 || !G.v2d) return; /* !G.v2d should never happen */
888         
889         event = pupmenu("Snap %t|Selection -> Pixels%x1|Selection -> Cursor%x2|Cursor-> Pixel%x3|Cursor-> Selection%x4");
890         switch (event) {
891                 case 1:
892                     if (snap_uv_sel_to_pixels()) {
893                         BIF_undo_push("Snap UV Selection to Pixels");
894                         object_uvs_changed(OBACT);
895                     }
896                     break;
897                 case 2:
898                     if (snap_uv_sel_to_curs()) {
899                         BIF_undo_push("Snap UV Selection to Cursor");
900                         object_uvs_changed(OBACT);
901                     }
902                     break;
903                 case 3:
904                     snap_uv_curs_to_pixels();
905                     scrarea_queue_winredraw(curarea);
906                     break;
907                 case 4:
908                     if (snap_uv_curs_to_sel())
909                         allqueue(REDRAWIMAGE, 0);
910                     break;
911         }
912 }
913
914
915 /** This is an ugly function to set the Tface selection flags depending
916   * on whether its UV coordinates are inside the normalized 
917   * area with radius rad and offset offset. These coordinates must be
918   * normalized to 1.0 
919   * Just for readability...
920   */
921
922 void sel_uvco_inside_radius(short sel, EditFace *efa, MTFace *tface, int index, float *offset, float *ell, short select_index)
923 {
924         // normalized ellipse: ell[0] = scaleX,
925         //                        [1] = scaleY
926
927         float *uv = tface->uv[index];
928         float x, y, r2;
929
930         x = (uv[0] - offset[0]) * ell[0];
931         y = (uv[1] - offset[1]) * ell[1];
932
933         r2 = x * x + y * y;
934         if (r2 < 1.0) {
935                 if (sel == LEFTMOUSE)   SIMA_UVSEL_SET(efa, tface, select_index);
936                 else                                    SIMA_UVSEL_UNSET(efa, tface, select_index);
937         }
938 }
939
940 // see below:
941 /** gets image dimensions of the 2D view 'v' */
942 static void getSpaceImageDimension(SpaceImage *sima, float *xy)
943 {
944         ImBuf *ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser);
945
946         if (ibuf) {
947                 xy[0] = ibuf->x * sima->zoom;
948                 xy[1] = ibuf->y * sima->zoom;
949         } else {
950                 xy[0] = 256 * sima->zoom;
951                 xy[1] = 256 * sima->zoom;
952         }
953 }
954
955 /** Callback function called by circle_selectCB to enable 
956   * brush select in UV editor.
957   */
958
959 void uvedit_selectionCB(short selecting, Object *editobj, short *mval, float rad) 
960 {
961         EditMesh *em = G.editMesh;
962         EditFace *efa;
963         float offset[2];
964         MTFace *tface;
965         float ellipse[2]; // we need to deal with ellipses, as
966                           // non square textures require for circle
967                                           // selection. this ellipse is normalized; r = 1.0
968
969         getSpaceImageDimension(curarea->spacedata.first, ellipse);
970         ellipse[0] /= rad;
971         ellipse[1] /= rad;
972
973         areamouseco_to_ipoco(G.v2d, mval, &offset[0], &offset[1]);
974         
975         if (selecting) {
976                 for (efa= em->faces.first; efa; efa= efa->next) {
977                         tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
978                         sel_uvco_inside_radius(selecting, efa, tface, 0, offset, ellipse, 0);
979                         sel_uvco_inside_radius(selecting, efa, tface, 1, offset, ellipse, 1);
980                         sel_uvco_inside_radius(selecting, efa, tface, 2, offset, ellipse, 2);
981                         if (efa->v4)
982                                 sel_uvco_inside_radius(selecting, efa, tface, 3, offset, ellipse, 3);
983                 }
984
985                 if(G.f & G_DRAWFACES) { /* full redraw only if necessary */
986                         draw_sel_circle(0, 0, 0, 0, 0); /* signal */
987                         force_draw(0);
988                 }
989                 else { /* force_draw() is no good here... */
990                         glDrawBuffer(GL_FRONT);
991                         draw_uvs_sima();
992                         bglFlush();
993                         glDrawBuffer(GL_BACK);
994                 }
995                 
996                 
997                 if (selecting == LEFTMOUSE)     EM_select_flush();
998                 else                                            EM_deselect_flush();
999                 
1000                 if (G.sima->lock && (G.sima->flag & SI_SYNC_UVSEL))
1001                         force_draw_plus(SPACE_VIEW3D, 0);
1002         }
1003 }
1004
1005
1006 void mouseco_to_curtile(void)
1007 {
1008         float fx, fy;
1009         short mval[2];
1010         
1011         if( is_uv_tface_editing_allowed()==0) return;
1012
1013         if(G.sima->image && G.sima->image->tpageflag & IMA_TILES) {
1014                 
1015                 G.sima->flag |= SI_EDITTILE;
1016                 
1017                 while(get_mbut()&L_MOUSE) {
1018                         
1019                         calc_image_view(G.sima, 'f');
1020                         
1021                         getmouseco_areawin(mval);
1022                         areamouseco_to_ipoco(G.v2d, mval, &fx, &fy);
1023
1024                         if(fx>=0.0 && fy>=0.0 && fx<1.0 && fy<1.0) {
1025                         
1026                                 fx= (fx)*G.sima->image->xrep;
1027                                 fy= (fy)*G.sima->image->yrep;
1028                                 
1029                                 mval[0]= fx;
1030                                 mval[1]= fy;
1031                                 
1032                                 G.sima->curtile= mval[1]*G.sima->image->xrep + mval[0];
1033                         }
1034
1035                         scrarea_do_windraw(curarea);
1036                         screen_swapbuffers();
1037                 }
1038                 
1039                 G.sima->flag &= ~SI_EDITTILE;
1040
1041                 image_set_tile(G.sima, 2);
1042
1043                 allqueue(REDRAWVIEW3D, 0);
1044                 scrarea_queue_winredraw(curarea);
1045         }
1046 }
1047
1048 /* Could be used for other 2D views also */
1049 void mouseco_to_cursor_sima(void)
1050 {
1051         short mval[2];
1052         getmouseco_areawin(mval);
1053         areamouseco_to_ipoco(G.v2d, mval, &G.v2d->cursor[0], &G.v2d->cursor[1]);
1054         scrarea_queue_winredraw(curarea);
1055 }
1056
1057 void stitch_uv_tface(int mode)
1058 {
1059         MTFace *tf;
1060         int a, vtot;
1061         float newuv[2], limit[2];
1062         UvMapVert *vlist, *iterv, *v;
1063         EditMesh *em = G.editMesh;
1064         EditVert *ev;
1065         EditFace *efa;
1066         
1067         struct UvVertMap *vmap;
1068         
1069         
1070         if(is_uv_tface_editing_allowed()==0)
1071                 return;
1072         if(G.sima->flag & SI_SYNC_UVSEL) {
1073                 error("Can't stitch when Sync Mesh Selection is enabled");
1074                 return;
1075         }
1076         
1077         limit[0]= limit[1]= 20.0;
1078         if(mode==1) {
1079                 add_numbut(0, NUM|FLO, "Limit:", 0.1, 1000.0, &limit[0], NULL);
1080                 if (!do_clever_numbuts("Stitch UVs", 1, REDRAW))
1081                         return;
1082         }
1083
1084         limit[0]= limit[1]= limit[0]/256.0;
1085         if(G.sima->image) {
1086                 ImBuf *ibuf= BKE_image_get_ibuf(G.sima->image, &G.sima->iuser);
1087
1088                 if(ibuf && ibuf->x > 0 && ibuf->y > 0) {
1089                         limit[1]= limit[0]/(float)ibuf->y;
1090                         limit[0]= limit[0]/(float)ibuf->x;
1091                 }
1092         }
1093
1094         /*vmap= make_uv_vert_map(me->mface, tf, me->totface, me->totvert, 1, limit);*/
1095         EM_init_index_arrays(0, 0, 1);
1096         vmap= make_uv_vert_map_EM(1, 0, limit);
1097         if(vmap == NULL)
1098                 return;
1099
1100         if(mode==0) {
1101                 for(a=0, ev= em->verts.first; ev; a++, ev= ev->next) {
1102                         v = get_uv_map_vert_EM(vmap, a);
1103
1104                         if(v == NULL)
1105                                 continue;
1106
1107                         newuv[0]= 0; newuv[1]= 0;
1108                         vtot= 0;
1109
1110                         for(iterv=v; iterv; iterv=iterv->next) {
1111                                 efa = EM_get_face_for_index(iterv->f);
1112                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1113                                 if (tf->flag & TF_SEL_MASK(iterv->tfindex)) {
1114                                         newuv[0] += tf->uv[iterv->tfindex][0];
1115                                         newuv[1] += tf->uv[iterv->tfindex][1];
1116                                         vtot++;
1117                                 }
1118                         }
1119
1120                         if (vtot > 1) {
1121                                 newuv[0] /= vtot; newuv[1] /= vtot;
1122
1123                                 for(iterv=v; iterv; iterv=iterv->next) {
1124                                         efa = EM_get_face_for_index(iterv->f);
1125                                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1126                                         if (tf->flag & TF_SEL_MASK(iterv->tfindex)) {
1127                                                 tf->uv[iterv->tfindex][0]= newuv[0];
1128                                                 tf->uv[iterv->tfindex][1]= newuv[1];
1129                                         }
1130                                 }
1131                         }
1132                 }
1133         } else if(mode==1) {
1134                 for(a=0, ev= em->verts.first; ev; a++, ev= ev->next) {
1135                         vlist= get_uv_map_vert_EM(vmap, a);
1136
1137                         while(vlist) {
1138                                 newuv[0]= 0; newuv[1]= 0;
1139                                 vtot= 0;
1140
1141                                 for(iterv=vlist; iterv; iterv=iterv->next) {
1142                                         if((iterv != vlist) && iterv->separate)
1143                                                 break;
1144                                         efa = EM_get_face_for_index(iterv->f);
1145                                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1146                                         
1147                                         if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
1148                                                 newuv[0] += tf->uv[iterv->tfindex][0];
1149                                                 newuv[1] += tf->uv[iterv->tfindex][1];
1150                                                 vtot++;
1151                                         }
1152                                 }
1153
1154                                 if (vtot > 1) {
1155                                         newuv[0] /= vtot; newuv[1] /= vtot;
1156
1157                                         for(iterv=vlist; iterv; iterv=iterv->next) {
1158                                                 if((iterv != vlist) && iterv->separate)
1159                                                         break;
1160                                                 efa = EM_get_face_for_index(iterv->f);
1161                                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1162                                                 if (tf->flag & TF_SEL_MASK(iterv->tfindex)) {
1163                                                         tf->uv[iterv->tfindex][0]= newuv[0];
1164                                                         tf->uv[iterv->tfindex][1]= newuv[1];
1165                                                 }
1166                                         }
1167                                 }
1168                                 vlist= iterv;
1169                         }
1170                 }
1171         }
1172
1173         free_uv_vert_map_EM(vmap);
1174         EM_free_index_arrays();
1175         
1176         if(G.sima->flag & SI_BE_SQUARE) be_square_tface_uv(em);
1177
1178         BIF_undo_push("Stitch UV");
1179
1180         object_uvs_changed(OBACT);
1181 }
1182
1183 void select_linked_tface_uv(int mode) /* TODO */
1184 {
1185         EditMesh *em= G.editMesh;
1186         EditFace *efa, *nearestefa=NULL;
1187         MTFace *tf, *nearesttf=NULL;
1188         UvVertMap *vmap;
1189         UvMapVert *vlist, *iterv, *startv;
1190         unsigned int *stack, stacksize= 0, nearestv;
1191         char *flag;
1192         int a, nearestuv, i, nverts, j;
1193         float limit[2];
1194         if(is_uv_tface_editing_allowed()==0)
1195                 return;
1196
1197         if(G.sima->flag & SI_SYNC_UVSEL) {
1198                 error("Can't select linked when Sync Mesh Selection is enabled");
1199                 return;
1200         }
1201         
1202         if (mode == 2) {
1203                 nearesttf= NULL;
1204                 nearestuv= 0;
1205         }
1206         if (mode!=2) {
1207                 find_nearest_uv(&nearesttf, &nearestefa, &nearestv, &nearestuv);
1208                 if(nearesttf==NULL)
1209                         return;
1210         }
1211
1212         get_connected_limit_tface_uv(limit);
1213         vmap= make_uv_vert_map_EM(1, 1, limit);
1214         if(vmap == NULL)
1215                 return;
1216
1217         stack= MEM_mallocN(sizeof(*stack)* BLI_countlist(&em->faces), "UvLinkStack");
1218         flag= MEM_callocN(sizeof(*flag)*BLI_countlist(&em->faces), "UvLinkFlag");
1219
1220         if (mode == 2) {
1221                 for (a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
1222                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1223                         if (SIMA_FACEDRAW_CHECK(efa, tf)) {
1224                                 if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) {
1225                                         stack[stacksize]= a;
1226                                         stacksize++;
1227                                         flag[a]= 1;
1228                                 }
1229                         }
1230                 }
1231         } else {
1232                 for (a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
1233                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1234                         if(tf == nearesttf) {
1235                                 stack[stacksize]= a;
1236                                 stacksize++;
1237                                 flag[a]= 1;
1238                                 break;
1239                         }
1240                 }
1241         }
1242
1243         while(stacksize > 0) {
1244                 stacksize--;
1245                 a= stack[stacksize];
1246                 
1247                 for (j=0, efa= em->faces.first; efa; efa= efa->next, j++) {
1248                         if (j==a) {
1249                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1250                                 break;
1251                         }
1252                 }
1253
1254                 nverts= efa->v4? 4: 3;
1255
1256                 for(i=0; i<nverts; i++) {
1257                         /* make_uv_vert_map_EM sets verts tmp.l to the indicies */
1258                         vlist= get_uv_map_vert_EM(vmap, (*(&efa->v1 + i))->tmp.l);
1259                         
1260                         startv= vlist;
1261
1262                         for(iterv=vlist; iterv; iterv=iterv->next) {
1263                                 if(iterv->separate)
1264                                         startv= iterv;
1265                                 if(iterv->f == a)
1266                                         break;
1267                         }
1268
1269                         for(iterv=startv; iterv; iterv=iterv->next) {
1270                                 if((startv != iterv) && (iterv->separate))
1271                                         break;
1272                                 else if(!flag[iterv->f]) {
1273                                         flag[iterv->f]= 1;
1274                                         stack[stacksize]= iterv->f;;
1275                                         stacksize++;
1276                                 }
1277                         }
1278                 }
1279         }
1280
1281         if(mode==0 || mode==2) {
1282                 for (a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
1283                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1284                         if(flag[a])
1285                                 tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1286                         else
1287                                 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1288                 }
1289         }
1290         else if(mode==1) {
1291                 for (a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
1292                         if(flag[a]) {
1293                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1294                                 if (efa->v4) {
1295                                         if((tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)))
1296                                                 break;
1297                                 }
1298                                 else if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
1299                                         break;
1300                         }
1301                 }
1302
1303                 if (efa) {
1304                         for (a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
1305                                 if(flag[a]) {
1306                                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1307                                         tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1308                                 }
1309                         }
1310                 }
1311                 else {
1312                         for (a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
1313                                 if(flag[a]) {
1314                                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1315                                         tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1316                                 }
1317                         }
1318                 }
1319         }
1320         
1321         MEM_freeN(stack);
1322         MEM_freeN(flag);
1323         free_uv_vert_map_EM(vmap);
1324
1325         BIF_undo_push("Select linked UV");
1326         scrarea_queue_winredraw(curarea);
1327 }
1328
1329 void unlink_selection(void)
1330 {
1331         EditMesh *em= G.editMesh;
1332         EditFace *efa;
1333         MTFace *tface;
1334
1335         if( is_uv_tface_editing_allowed()==0 ) return;
1336
1337         if(G.sima->flag & SI_SYNC_UVSEL) {
1338                 error("Can't select unlinked when Sync Mesh Selection is enabled");
1339                 return;
1340         }
1341         
1342         for (efa= em->faces.first; efa; efa= efa->next) {
1343                 tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1344                 if (SIMA_FACEDRAW_CHECK(efa, tface)) {
1345                         if(efa->v4) {
1346                                 if(~tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4))
1347                                         tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1348                         } else {
1349                                 if(~tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
1350                                         tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3);
1351                         }
1352                 }
1353         }
1354         
1355         BIF_undo_push("Unlink UV selection");
1356         scrarea_queue_winredraw(curarea);
1357 }
1358
1359 void toggle_uv_select(int mode)
1360 {
1361         switch(mode){
1362         case 'f':
1363                 G.sima->flag ^= SI_SELACTFACE;
1364                 break;
1365         case 's':
1366                 G.sima->flag ^= SI_STICKYUVS; 
1367                 if (G.sima->flag & SI_STICKYUVS) G.sima->flag &= ~SI_LOCALSTICKY;
1368                 else G.sima->flag |= SI_LOCALSTICKY;
1369                 break;
1370         case 'l': 
1371                  G.sima->flag ^= SI_LOCALSTICKY;
1372                  if (G.sima->flag & SI_LOCALSTICKY) G.sima->flag &= ~SI_STICKYUVS;
1373                 break;
1374         case 'o':
1375                 G.sima->flag &= ~SI_STICKYUVS; 
1376                 G.sima->flag &= ~SI_LOCALSTICKY;
1377                 break;
1378         }
1379         allqueue(REDRAWIMAGE, 0);
1380 }
1381
1382 void pin_tface_uv(int mode)
1383 {
1384         EditMesh *em = G.editMesh;
1385         EditFace *efa;
1386         MTFace *tface;
1387         
1388         if( is_uv_tface_editing_allowed()==0 ) return;
1389         
1390         for (efa= em->faces.first; efa; efa= efa->next) {
1391                 tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1392                 if (SIMA_FACEDRAW_CHECK(efa, tface)) {
1393                         if(mode ==1) {
1394                                 if(SIMA_UVSEL_CHECK(efa, tface, 0)) tface->unwrap |= TF_PIN1;
1395                                 if(SIMA_UVSEL_CHECK(efa, tface, 1)) tface->unwrap |= TF_PIN2;
1396                                 if(SIMA_UVSEL_CHECK(efa, tface, 2)) tface->unwrap |= TF_PIN3;
1397                                 if(efa->v4)
1398                                         if(SIMA_UVSEL_CHECK(efa, tface, 3)) tface->unwrap |= TF_PIN4;
1399                         }
1400                         else if (mode ==0) {
1401                                 if(SIMA_UVSEL_CHECK(efa, tface, 0)) tface->unwrap &= ~TF_PIN1;
1402                                 if(SIMA_UVSEL_CHECK(efa, tface, 1)) tface->unwrap &= ~TF_PIN2;
1403                                 if(SIMA_UVSEL_CHECK(efa, tface, 2)) tface->unwrap &= ~TF_PIN3;
1404                                 if(efa->v4)
1405                                         if(SIMA_UVSEL_CHECK(efa, tface, 3)) tface->unwrap &= ~TF_PIN4;
1406                         }
1407                 }
1408         }
1409         
1410         BIF_undo_push("Pin UV");
1411         scrarea_queue_winredraw(curarea);
1412 }
1413
1414 void select_pinned_tface_uv(void)
1415 {
1416         EditMesh *em= G.editMesh;
1417         EditFace *efa;
1418         MTFace *tface;
1419         
1420         if( is_uv_tface_editing_allowed()==0 ) return;
1421         
1422         for (efa= em->faces.first; efa; efa= efa->next) {
1423                 tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1424                 if (SIMA_FACEDRAW_CHECK(efa, tface)) {
1425                         if (tface->unwrap & TF_PIN1) SIMA_UVSEL_SET(efa, tface, 0);
1426                         if (tface->unwrap & TF_PIN2) SIMA_UVSEL_SET(efa, tface, 1);
1427                         if (tface->unwrap & TF_PIN3) SIMA_UVSEL_SET(efa, tface, 2);
1428                         if(efa->v4) {
1429                                 if (tface->unwrap & TF_PIN4) SIMA_UVSEL_SET(efa, tface, 3);
1430                         }
1431                         
1432                 }
1433         }
1434         
1435         if (G.sima->flag & SI_SYNC_UVSEL) {
1436                 allqueue(REDRAWVIEW3D, 0); /* mesh selection has changed */
1437         }
1438         
1439         BIF_undo_push("Select Pinned UVs");
1440         scrarea_queue_winredraw(curarea);
1441 }
1442
1443 int minmax_tface_uv(float *min, float *max)
1444 {
1445         EditMesh *em= G.editMesh;
1446         EditFace *efa;
1447         MTFace *tf;
1448         int sel;
1449         
1450         if( is_uv_tface_editing_allowed()==0 ) return 0;
1451
1452         INIT_MINMAX2(min, max);
1453
1454         sel= 0;
1455         for (efa= em->faces.first; efa; efa= efa->next) {
1456                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1457                 if (SIMA_FACEDRAW_CHECK(efa, tf)) {
1458                         if (SIMA_UVSEL_CHECK(efa, tf, 0))                               DO_MINMAX2(tf->uv[0], min, max);
1459                         if (SIMA_UVSEL_CHECK(efa, tf, 1))                               DO_MINMAX2(tf->uv[1], min, max);
1460                         if (SIMA_UVSEL_CHECK(efa, tf, 2))                               DO_MINMAX2(tf->uv[2], min, max);
1461                         if (efa->v4 && (SIMA_UVSEL_CHECK(efa, tf, 3)))  DO_MINMAX2(tf->uv[3], min, max);
1462                         sel = 1;
1463                 }
1464         }
1465         return sel;
1466 }
1467
1468 int cent_tface_uv(float *cent, int mode)
1469 {
1470         float min[2], max[2];
1471         short change= 0;
1472         
1473         if (mode==0) {
1474                 if (minmax_tface_uv(min, max))
1475                         change = 1;
1476
1477         } else if (mode==1) {
1478                 EditFace *efa;
1479                 MTFace *tf;
1480                 INIT_MINMAX2(min, max);
1481                 
1482                 for (efa= G.editMesh->faces.first; efa; efa= efa->next) {
1483                         tf = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
1484                         if (SIMA_FACEDRAW_CHECK(efa, tf)) {
1485                                 if (SIMA_UVSEL_CHECK(efa, tf, 0))                               { DO_MINMAX2(tf->uv[0], min, max);      change= 1;}
1486                                 if (SIMA_UVSEL_CHECK(efa, tf, 1))                               { DO_MINMAX2(tf->uv[1], min, max);      change= 1;}
1487                                 if (SIMA_UVSEL_CHECK(efa, tf, 2))                               { DO_MINMAX2(tf->uv[2], min, max);      change= 1;}
1488                                 if (efa->v4 && (SIMA_UVSEL_CHECK(efa, tf, 3)))  { DO_MINMAX2(tf->uv[3], min, max);      change= 1;}
1489                         }
1490                 }
1491         }
1492         
1493         if (change) {
1494                 cent[0]= (min[0]+max[0])/2.0;
1495                 cent[1]= (min[1]+max[1])/2.0;
1496                 return 1;
1497         }
1498         return 0;
1499 }
1500
1501 static void sima_show_info(int channels, int x, int y, char *cp, float *fp, int *zp, float *zpf)
1502 {
1503         short ofs;
1504         char str[256];
1505         
1506         ofs= sprintf(str, "X: %d Y: %d ", x, y);
1507         if(cp)
1508                 ofs+= sprintf(str+ofs, "| R: %d G: %d B: %d A: %d ", cp[0], cp[1], cp[2], cp[3]);
1509         if(fp) {
1510                 if(channels==4)
1511                         ofs+= sprintf(str+ofs, "| R: %.3f G: %.3f B: %.3f A: %.3f ", fp[0], fp[1], fp[2], fp[3]);
1512                 else if(channels==1)
1513                         ofs+= sprintf(str+ofs, "| Val: %.3f ", fp[0]);
1514                 else if(channels==3)
1515                         ofs+= sprintf(str+ofs, "| R: %.3f G: %.3f B: %.3f ", fp[0], fp[1], fp[2]);
1516         }
1517         if(zp)
1518                 ofs+= sprintf(str+ofs, "| Z: %.4f ", 0.5+0.5*( ((float)*zp)/(float)0x7fffffff));
1519         if(zpf)
1520                 ofs+= sprintf(str+ofs, "| Z: %.3f ", *zpf);
1521         
1522         glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
1523         glEnable(GL_BLEND);
1524         
1525         glColor4f(.0,.0,.0,.25);
1526         glRectf(0.0, 0.0, curarea->winx, 30.0);
1527         glDisable(GL_BLEND);
1528         
1529         glColor3ub(255, 255, 255);
1530         glRasterPos2i(10, 10);
1531         
1532         BMF_DrawString(G.fonts, str);
1533
1534 }
1535
1536 void sima_sample_color(void)
1537 {
1538         ImBuf *ibuf= BKE_image_get_ibuf(G.sima->image, &G.sima->iuser);
1539         float fx, fy;
1540         short mval[2], mvalo[2], firsttime=1;
1541         
1542         if(ibuf==NULL)
1543                 return;
1544         
1545         calc_image_view(G.sima, 'f');
1546         getmouseco_areawin(mvalo);
1547         
1548         while(get_mbut() & L_MOUSE) {
1549                 
1550                 getmouseco_areawin(mval);
1551                 if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || firsttime) {
1552                         firsttime= 0;
1553                         areamouseco_to_ipoco(G.v2d, mval, &fx, &fy);
1554                         
1555                         if(fx>=0.0 && fy>=0.0 && fx<1.0 && fy<1.0) {
1556                                 float *fp= NULL, *zpf= NULL;
1557                                 int *zp= NULL;
1558                                 char *cp= NULL;
1559                                 
1560                                 int x= (int) (fx*ibuf->x);
1561                                 int y= (int) (fy*ibuf->y);
1562                                 
1563                                 if(x>=ibuf->x) x= ibuf->x-1;
1564                                 if(y>=ibuf->y) y= ibuf->y-1;
1565                                 
1566                                 if(ibuf->rect)
1567                                         cp= (char *)(ibuf->rect + y*ibuf->x + x);
1568                                 if(ibuf->zbuf)
1569                                         zp= ibuf->zbuf + y*ibuf->x + x;
1570                                 if(ibuf->zbuf_float)
1571                                         zpf= ibuf->zbuf_float + y*ibuf->x + x;
1572                                 if(ibuf->rect_float)
1573                                         fp= (ibuf->rect_float + (ibuf->channels)*(y*ibuf->x + x));
1574                                         
1575                                 if(G.sima->cumap) {
1576                                         float vec[3];
1577                                         if(fp==NULL) {
1578                                                 fp= vec;
1579                                                 vec[0]= (float)cp[0]/255.0f;
1580                                                 vec[1]= (float)cp[1]/255.0f;
1581                                                 vec[2]= (float)cp[2]/255.0f;
1582                                         }
1583                                         
1584                                         if(ibuf->channels==4) {
1585                                                 if(G.qual & LR_CTRLKEY) {
1586                                                         curvemapping_set_black_white(G.sima->cumap, NULL, fp);
1587                                                         curvemapping_do_ibuf(G.sima->cumap, ibuf);
1588                                                 }
1589                                                 else if(G.qual & LR_SHIFTKEY) {
1590                                                         curvemapping_set_black_white(G.sima->cumap, fp, NULL);
1591                                                         curvemapping_do_ibuf(G.sima->cumap, ibuf);
1592                                                 }
1593                                         }
1594                                 }
1595                                 
1596                                 scrarea_do_windraw(curarea);
1597                                 myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
1598                                 glLoadIdentity();
1599                                 sima_show_info(ibuf->channels, x, y, cp, fp, zp, zpf);
1600                                 screen_swapbuffers();
1601                         }
1602                         
1603                 }
1604                 BIF_wait_for_statechange();
1605         }
1606         
1607         scrarea_queue_winredraw(curarea);
1608 }
1609
1610 /* Image functions */
1611
1612 static void load_image_filesel(char *str)       /* called from fileselect */
1613 {
1614         Image *ima= NULL;
1615
1616         ima= BKE_add_image_file(str);
1617         if(ima) {
1618                 BKE_image_signal(ima, &G.sima->iuser, IMA_SIGNAL_RELOAD);
1619                 image_changed(G.sima, ima);
1620         }
1621         BIF_undo_push("Load image UV");
1622         allqueue(REDRAWIMAGE, 0);
1623 }
1624
1625 static void replace_image_filesel(char *str)            /* called from fileselect */
1626 {
1627         if (!G.sima->image)
1628                 return;
1629         
1630         strncpy(G.sima->image->name, str, sizeof(G.sima->image->name)-1); /* we cant do much if the str is longer then 240 :/ */
1631         BKE_image_signal(G.sima->image, &G.sima->iuser, IMA_SIGNAL_RELOAD);
1632         BIF_undo_push("Replace image UV");
1633         allqueue(REDRAWIMAGE, 0);
1634         allqueue(REDRAWVIEW3D, 0);
1635 }
1636
1637
1638 static void save_image_doit(char *name)
1639 {
1640         Image *ima= G.sima->image;
1641         ImBuf *ibuf= BKE_image_get_ibuf(ima, &G.sima->iuser);
1642         int len;
1643         char str[FILE_MAXDIR+FILE_MAXFILE];
1644
1645         if (ibuf) {
1646                 BLI_strncpy(str, name, sizeof(str));
1647
1648                 BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
1649                 
1650                 if(G.scene->r.scemode & R_EXTENSION) 
1651                         BKE_add_image_extension(str, G.sima->imtypenr);
1652                 
1653                 if (saveover(str)) {
1654                         
1655                         /* enforce user setting for RGB or RGBA, but skip BW */
1656                         if(G.scene->r.planes==32)
1657                                 ibuf->depth= 32;
1658                         else if(G.scene->r.planes==24)
1659                                 ibuf->depth= 24;
1660                         
1661                         waitcursor(1);
1662                         if(G.sima->imtypenr==R_MULTILAYER) {
1663                                 RenderResult *rr= BKE_image_get_renderresult(ima);
1664                                 if(rr) {
1665                                         RE_WriteRenderResult(rr, str, G.scene->r.quality);
1666                                         
1667                                         BLI_strncpy(ima->name, name, sizeof(ima->name));
1668                                         BLI_strncpy(ibuf->name, str, sizeof(ibuf->name));
1669                                         
1670                                         /* should be function? nevertheless, saving only happens here */
1671                                         for(ibuf= ima->ibufs.first; ibuf; ibuf= ibuf->next)
1672                                                 ibuf->userflags &= ~IB_BITMAPDIRTY;
1673                                         
1674                                 }
1675                                 else error("Did not write, no Multilayer Image");
1676                         }
1677                         else if (BKE_write_ibuf(ibuf, str, G.sima->imtypenr, G.scene->r.subimtype, G.scene->r.quality)) {
1678                                 BLI_strncpy(ima->name, name, sizeof(ima->name));
1679                                 BLI_strncpy(ibuf->name, str, sizeof(ibuf->name));
1680                                 
1681                                 ibuf->userflags &= ~IB_BITMAPDIRTY;
1682                                 
1683                                 /* change type? */
1684                                 if( ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC_VIEWER)) {
1685                                         ima->source= IMA_SRC_FILE;
1686                                         ima->type= IMA_TYPE_IMAGE;
1687                                 }
1688                                 if(ima->type==IMA_TYPE_R_RESULT)
1689                                         ima->type= IMA_TYPE_IMAGE;
1690                                 
1691                                 /* name image as how we saved it */
1692                                 len= strlen(str);
1693                                 while (len > 0 && str[len - 1] != '/' && str[len - 1] != '\\') len--;
1694                                 rename_id(&ima->id, str+len);
1695                         } 
1696                         else {
1697                                 error("Couldn't write image: %s", str);
1698                         }
1699
1700                         allqueue(REDRAWHEADERS, 0);
1701                         allqueue(REDRAWBUTSSHADING, 0);
1702
1703                         waitcursor(0);
1704                 }
1705         }
1706 }
1707
1708 void open_image_sima(short imageselect)
1709 {
1710         char name[FILE_MAXDIR+FILE_MAXFILE];
1711
1712         if(G.sima->image)
1713                 strcpy(name, G.sima->image->name);
1714         else
1715                 strcpy(name, U.textudir);
1716
1717         if(imageselect)
1718                 activate_imageselect(FILE_SPECIAL, "Open Image", name, load_image_filesel);
1719         else
1720                 activate_fileselect(FILE_SPECIAL, "Open Image", name, load_image_filesel);
1721 }
1722
1723 void replace_image_sima(short imageselect)
1724 {
1725         char name[FILE_MAXDIR+FILE_MAXFILE];
1726
1727         if(G.sima->image)
1728                 strcpy(name, G.sima->image->name);
1729         else
1730                 strcpy(name, U.textudir);
1731         
1732         if(imageselect)
1733                 activate_imageselect(FILE_SPECIAL, "Replace Image", name, replace_image_filesel);
1734         else
1735                 activate_fileselect(FILE_SPECIAL, "Replace Image", name, replace_image_filesel);
1736 }
1737
1738
1739 static char *filesel_imagetype_string(Image *ima)
1740 {
1741         char *strp, *str= MEM_callocN(14*32, "menu for filesel");
1742         
1743         strp= str;
1744         str += sprintf(str, "Save Image as: %%t|");
1745         str += sprintf(str, "Targa %%x%d|", R_TARGA);
1746         str += sprintf(str, "Targa Raw %%x%d|", R_RAWTGA);
1747         str += sprintf(str, "PNG %%x%d|", R_PNG);
1748         str += sprintf(str, "BMP %%x%d|", R_BMP);
1749         str += sprintf(str, "Jpeg %%x%d|", R_JPEG90);
1750         str += sprintf(str, "Iris %%x%d|", R_IRIS);
1751         if(G.have_libtiff)
1752                 str += sprintf(str, "Tiff %%x%d|", R_TIFF);
1753         str += sprintf(str, "Radiance HDR %%x%d|", R_RADHDR);
1754         str += sprintf(str, "Cineon %%x%d|", R_CINEON);
1755         str += sprintf(str, "DPX %%x%d|", R_DPX);
1756 #ifdef WITH_OPENEXR
1757         str += sprintf(str, "OpenEXR %%x%d|", R_OPENEXR);
1758         /* saving sequences of multilayer won't work, they copy buffers  */
1759         if(ima->source==IMA_SRC_SEQUENCE && ima->type==IMA_TYPE_MULTILAYER);
1760         else str += sprintf(str, "MultiLayer %%x%d|", R_MULTILAYER);
1761 #endif  
1762         return strp;
1763 }
1764
1765 /* always opens fileselect */
1766 void save_as_image_sima(void)
1767 {
1768         Image *ima = G.sima->image;
1769         ImBuf *ibuf= BKE_image_get_ibuf(ima, &G.sima->iuser);
1770         char name[FILE_MAXDIR+FILE_MAXFILE];
1771
1772         if (ima) {
1773                 strcpy(name, ima->name);
1774
1775                 if (ibuf) {
1776                         char *strp;
1777                         
1778                         strp= filesel_imagetype_string(ima);
1779                         
1780                         /* cant save multilayer sequence, ima->rr isn't valid for a specific frame */
1781                         if(ima->rr && !(ima->source==IMA_SRC_SEQUENCE && ima->type==IMA_TYPE_MULTILAYER))
1782                                 G.sima->imtypenr= R_MULTILAYER;
1783                         else if(ima->type==IMA_TYPE_R_RESULT)
1784                                 G.sima->imtypenr= G.scene->r.imtype;
1785                         else G.sima->imtypenr= BKE_ftype_to_imtype(ibuf->ftype);
1786                         
1787                         activate_fileselect_menu(FILE_SPECIAL, "Save Image", name, strp, &G.sima->imtypenr, save_image_doit);
1788                 }
1789         }
1790 }
1791
1792 /* if exists, saves over without fileselect */
1793 void save_image_sima(void)
1794 {
1795         Image *ima = G.sima->image;
1796         ImBuf *ibuf= BKE_image_get_ibuf(ima, &G.sima->iuser);
1797         char name[FILE_MAXDIR+FILE_MAXFILE];
1798
1799         if (ima) {
1800                 strcpy(name, ima->name);
1801
1802                 if (ibuf) {
1803                         if (BLI_exists(ibuf->name)) {
1804                                 if(BKE_image_get_renderresult(ima)) 
1805                                         G.sima->imtypenr= R_MULTILAYER;
1806                                 else 
1807                                         G.sima->imtypenr= BKE_ftype_to_imtype(ibuf->ftype);
1808                                 
1809                                 save_image_doit(ibuf->name);
1810                         }
1811                         else
1812                                 save_as_image_sima();
1813                 }
1814         }
1815 }
1816
1817 void save_image_sequence_sima(void)
1818 {
1819         ImBuf *ibuf;
1820         int tot= 0;
1821         char di[FILE_MAX], fi[FILE_MAX];
1822         
1823         if(G.sima->image==NULL)
1824                 return;
1825         if(G.sima->image->source!=IMA_SRC_SEQUENCE)
1826                 return;
1827         if(G.sima->image->type==IMA_TYPE_MULTILAYER) {
1828                 error("Cannot save Multilayer Sequences");
1829                 return;
1830         }
1831         
1832         /* get total */
1833         for(ibuf= G.sima->image->ibufs.first; ibuf; ibuf= ibuf->next) 
1834                 if(ibuf->userflags & IB_BITMAPDIRTY)
1835                         tot++;
1836         
1837         if(tot==0) {
1838                 notice("No Images have been changed");
1839                 return;
1840         }
1841         /* get a filename for menu */
1842         for(ibuf= G.sima->image->ibufs.first; ibuf; ibuf= ibuf->next) 
1843                 if(ibuf->userflags & IB_BITMAPDIRTY)
1844                         break;
1845         
1846         BLI_strncpy(di, ibuf->name, FILE_MAX);
1847         BLI_splitdirstring(di, fi);
1848         
1849         sprintf(fi, "%d Image(s) will be saved in %s", tot, di);
1850         if(okee(fi)) {
1851                 
1852                 for(ibuf= G.sima->image->ibufs.first; ibuf; ibuf= ibuf->next) {
1853                         if(ibuf->userflags & IB_BITMAPDIRTY) {
1854                                 char name[FILE_MAX];
1855                                 BLI_strncpy(name, ibuf->name, sizeof(name));
1856                                 
1857                                 BLI_convertstringcode(name, G.sce, 0);
1858
1859                                 if(0 == IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat)) {
1860                                         error("Could not write image", name);
1861                                         break;
1862                                 }
1863                                 printf("Saved: %s\n", ibuf->name);
1864                                 ibuf->userflags &= ~IB_BITMAPDIRTY;
1865                         }
1866                 }
1867         }
1868 }
1869
1870 void reload_image_sima(void)
1871 {
1872         if (G.sima ) {
1873                 BKE_image_signal(G.sima->image, &G.sima->iuser, IMA_SIGNAL_RELOAD);
1874                 /* image_changed(G.sima, 0); - do we really need this? */
1875         }
1876
1877         allqueue(REDRAWIMAGE, 0);
1878         allqueue(REDRAWVIEW3D, 0);
1879         BIF_preview_changed(ID_TE);
1880 }
1881
1882 void new_image_sima(void)
1883 {
1884         static int width= 256, height= 256;
1885         static short uvtestgrid= 0;
1886         static float color[] = {0, 0, 0, 1};
1887         char name[22];
1888         Image *ima;
1889         
1890         strcpy(name, "Untitled");
1891
1892         add_numbut(0, TEX, "Name:", 0, 21, name, NULL);
1893         add_numbut(1, NUM|INT, "Width:", 1, 5000, &width, NULL);
1894         add_numbut(2, NUM|INT, "Height:", 1, 5000, &height, NULL);
1895         add_numbut(3, COL, "", 0, 0, &color, NULL);
1896         add_numbut(4, NUM|FLO, "Alpha:", 0.0, 1.0, &color[3], NULL);
1897         add_numbut(5, TOG|SHO, "UV Test Grid", 0, 0, &uvtestgrid, NULL);
1898         if (!do_clever_numbuts("New Image", 6, REDRAW))
1899                 return;
1900
1901         ima = BKE_add_image_size(width, height, name, uvtestgrid, color);
1902         image_changed(G.sima, ima);
1903         BKE_image_signal(G.sima->image, &G.sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE);
1904         BIF_undo_push("Add image");
1905
1906         allqueue(REDRAWIMAGE, 0);
1907         allqueue(REDRAWVIEW3D, 0);
1908 }
1909
1910 void pack_image_sima()
1911 {
1912         Image *ima = G.sima->image;
1913
1914         if (ima) {
1915                 if(ima->source!=IMA_SRC_SEQUENCE && ima->source!=IMA_SRC_MOVIE) {
1916                         if (ima->packedfile) {
1917                                 if (G.fileflags & G_AUTOPACK)
1918                                         if (okee("Disable AutoPack?"))
1919                                                 G.fileflags &= ~G_AUTOPACK;
1920                                 
1921                                 if ((G.fileflags & G_AUTOPACK) == 0) {
1922                                         unpackImage(ima, PF_ASK);
1923                                         BIF_undo_push("Unpack image");
1924                                 }
1925                         }
1926                         else {
1927                                 ImBuf *ibuf= BKE_image_get_ibuf(ima, &G.sima->iuser);
1928                                 if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) {
1929                                         if(okee("Can't pack painted image. Use Repack as PNG?"))
1930                                                 BKE_image_memorypack(ima);
1931                                 }
1932                                 else {
1933                                         ima->packedfile = newPackedFile(ima->name);
1934                                         BIF_undo_push("Pack image");
1935                                 }
1936                         }
1937
1938                         allqueue(REDRAWBUTSSHADING, 0);
1939                         allqueue(REDRAWHEADERS, 0);
1940                 }
1941         }
1942 }
1943
1944
1945
1946 /* goes over all ImageUsers, and sets frame numbers if auto-refresh is set */
1947 void BIF_image_update_frame(void)
1948 {
1949         Tex *tex;
1950         
1951         /* texture users */
1952         for(tex= G.main->tex.first; tex; tex= tex->id.next) {
1953                 if(tex->type==TEX_IMAGE && tex->ima)
1954                         if(ELEM(tex->ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE))
1955                                 if(tex->iuser.flag & IMA_ANIM_ALWAYS)
1956                                         BKE_image_user_calc_imanr(&tex->iuser, G.scene->r.cfra, 0);
1957                 
1958         }
1959         /* image window, compo node users */
1960         if(G.curscreen) {
1961                 ScrArea *sa;
1962                 for(sa= G.curscreen->areabase.first; sa; sa= sa->next) {
1963                         if(sa->spacetype==SPACE_VIEW3D) {
1964                                 View3D *v3d= sa->spacedata.first;
1965                                 if(v3d->bgpic)
1966                                         if(v3d->bgpic->iuser.flag & IMA_ANIM_ALWAYS)
1967                                                 BKE_image_user_calc_imanr(&v3d->bgpic->iuser, G.scene->r.cfra, 0);
1968                         }
1969                         else if(sa->spacetype==SPACE_IMAGE) {
1970                                 SpaceImage *sima= sa->spacedata.first;
1971                                 if(sima->iuser.flag & IMA_ANIM_ALWAYS)
1972                                         BKE_image_user_calc_imanr(&sima->iuser, G.scene->r.cfra, 0);
1973                         }
1974                         else if(sa->spacetype==SPACE_NODE) {
1975                                 SpaceNode *snode= sa->spacedata.first;
1976                                 if((snode->treetype==NTREE_COMPOSIT) && (snode->nodetree)) {
1977                                         bNode *node;
1978                                         for(node= snode->nodetree->nodes.first; node; node= node->next) {
1979                                                 if(node->id && node->type==CMP_NODE_IMAGE) {
1980                                                         Image *ima= (Image *)node->id;
1981                                                         ImageUser *iuser= node->storage;
1982                                                         if(ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE))
1983                                                                 if(iuser->flag & IMA_ANIM_ALWAYS)
1984                                                                         BKE_image_user_calc_imanr(iuser, G.scene->r.cfra, 0);
1985                                                 }
1986                                         }
1987                                 }
1988                         }
1989                 }
1990         }
1991 }
1992
1993 void aspect_sima(SpaceImage *sima, float *x, float *y)
1994 {
1995         *x = *y = 1.0;
1996         
1997         if(             (sima->image == 0) ||
1998                         (sima->image->type == IMA_TYPE_R_RESULT) ||
1999                         (sima->image->type == IMA_TYPE_COMPOSITE) ||
2000                         (sima->image->tpageflag & IMA_TILES) ||
2001                         (sima->image->aspx==0.0 || sima->image->aspy==0.0)
2002         ) {
2003                 return;
2004         }
2005         
2006         /* x is always 1 */
2007         *y = sima->image->aspy / sima->image->aspx;
2008 }