97765690cebf52f86fec2af4dfdca80c22f4662c
[blender-staging.git] / source / blender / src / drawimage.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): Blender Foundation, 2002-2006
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <math.h>
31 #include <string.h>
32
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36
37 #ifdef WIN32
38 #include <io.h>
39 #else
40 #include <unistd.h>
41 #endif   
42 #include "MEM_guardedalloc.h"
43
44 #include "BLI_arithb.h"
45 #include "BLI_blenlib.h"
46 #include "BLI_editVert.h"
47
48 #include "IMB_imbuf.h"
49 #include "IMB_imbuf_types.h"
50
51 #include "DNA_brush_types.h"
52 #include "DNA_camera_types.h"
53 #include "DNA_color_types.h"
54 #include "DNA_image_types.h"
55 #include "DNA_gpencil_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"
60 #include "DNA_packedFile_types.h"
61 #include "DNA_scene_types.h"
62 #include "DNA_screen_types.h"
63 #include "DNA_space_types.h"
64 #include "DNA_texture_types.h"
65 #include "DNA_userdef_types.h"
66
67 #include "BKE_brush.h"
68 #include "BKE_colortools.h"
69 #include "BKE_utildefines.h"
70 #include "BKE_global.h"
71 #include "BKE_library.h"
72 #include "BKE_main.h"
73 #include "BKE_mesh.h"
74 #include "BKE_node.h"
75 #include "BKE_image.h"
76 #include "BKE_DerivedMesh.h"
77 #include "BKE_displist.h"
78 #include "BKE_object.h"
79
80 #include "BDR_editface.h"
81 #include "BDR_drawobject.h"
82 #include "BDR_drawmesh.h"
83 #include "BDR_gpencil.h"
84 #include "BDR_imagepaint.h"
85
86 #include "BIF_cursors.h"
87 #include "BIF_gl.h"
88 #include "BIF_graphics.h"
89 #include "BIF_mywindow.h"
90 #include "BIF_drawimage.h"
91 #include "BIF_drawgpencil.h"
92 #include "BIF_resources.h"
93 #include "BIF_interface.h"
94 #include "BIF_interface_icons.h"
95 #include "BIF_editsima.h"
96 #include "BIF_glutil.h"
97 #include "BIF_renderwin.h"
98 #include "BIF_space.h"
99 #include "BIF_screen.h"
100 #include "BIF_toolbox.h"
101 #include "BIF_transform.h"
102 #include "BIF_editmesh.h"
103
104 #include "BSE_drawipo.h"
105 #include "BSE_drawview.h"
106 #include "BSE_filesel.h"
107 #include "BSE_headerbuttons.h"
108 #include "BSE_node.h"
109 #include "BSE_trans_types.h"
110 #include "BSE_view.h"
111
112 #include "RE_pipeline.h"
113 #include "BMF_Api.h"
114
115 #include "PIL_time.h"
116
117 /* Modules used */
118 #include "mydevice.h"
119 #include "blendef.h"
120 #include "butspace.h"  // event codes
121 #include "winlay.h"
122
123 #include "interface.h"  /* bad.... but preview code needs UI info. Will solve... (ton) */
124
125 static unsigned char *alloc_alpha_clone_image(int *width, int *height)
126 {
127         Brush *brush = G.scene->toolsettings->imapaint.brush;
128         ImBuf *ibuf;
129         unsigned int size, alpha;
130         unsigned char *rect, *cp;
131
132         if(!brush || !brush->clone.image)
133                 return NULL;
134         
135         ibuf= BKE_image_get_ibuf(brush->clone.image, NULL);
136
137         if(!ibuf || !ibuf->rect)
138                 return NULL;
139
140         rect= MEM_dupallocN(ibuf->rect);
141         if(!rect)
142                 return NULL;
143
144         *width= ibuf->x;
145         *height= ibuf->y;
146
147         size= (*width)*(*height);
148         alpha= (unsigned char)255*brush->clone.alpha;
149         cp= rect;
150
151         while(size-- > 0) {
152                 cp[3]= alpha;
153                 cp += 4;
154         }
155
156         return rect;
157 }
158
159 static int image_preview_active(ScrArea *sa, float *xim, float *yim)
160 {
161         SpaceImage *sima= sa->spacedata.first;
162         
163         /* only when compositor shows, and image handler set */
164         if(sima->image && sima->image->type==IMA_TYPE_COMPOSITE) {
165                 short a;
166         
167                 for(a=0; a<SPACE_MAXHANDLER; a+=2) {
168                         if(sima->blockhandler[a] == IMAGE_HANDLER_PREVIEW) {
169                                 if(xim) *xim= (G.scene->r.size*G.scene->r.xsch)/100;
170                                 if(yim) *yim= (G.scene->r.size*G.scene->r.ysch)/100;
171                                 return 1;
172                         }
173                 }
174         }
175         return 0;
176 }
177
178
179 /**
180  * Sets up the fields of the View2D member of the SpaceImage struct
181  * This routine can be called in two modes:
182  * mode == 'f': float mode (0.0 - 1.0)
183  * mode == 'p': pixel mode (0 - size)
184  *
185  * @param     sima  the image space to update
186  * @param     mode  the mode to use for the update
187  * @return    void
188  *   
189  */
190 void calc_image_view(SpaceImage *sima, char mode)
191 {
192         float xim=256, yim=256;
193         float x1, y1;
194         
195         if(image_preview_active(curarea, &xim, &yim));
196         else if(sima->image) {
197                 ImBuf *ibuf= imagewindow_get_ibuf(sima);
198                 float xuser_asp, yuser_asp;
199                 
200                 image_pixel_aspect(sima->image, &xuser_asp, &yuser_asp);
201                 if(ibuf) {
202                         xim= ibuf->x * xuser_asp;
203                         yim= ibuf->y * yuser_asp;
204                 }
205                 else if( sima->image->type==IMA_TYPE_R_RESULT ) {
206                         /* not very important, just nice */
207                         xim= (G.scene->r.xsch*G.scene->r.size)/100;
208                         yim= (G.scene->r.ysch*G.scene->r.size)/100;
209                 }
210         }
211                 
212         sima->v2d.tot.xmin= 0;
213         sima->v2d.tot.ymin= 0;
214         sima->v2d.tot.xmax= xim;
215         sima->v2d.tot.ymax= yim;
216         
217         sima->v2d.mask.xmin= sima->v2d.mask.ymin= 0;
218         sima->v2d.mask.xmax= curarea->winx;
219         sima->v2d.mask.ymax= curarea->winy;
220
221
222         /* Which part of the image space do we see? */
223         /* Same calculation as in lrectwrite: area left and down*/
224         x1= curarea->winrct.xmin+(curarea->winx-sima->zoom*xim)/2;
225         y1= curarea->winrct.ymin+(curarea->winy-sima->zoom*yim)/2;
226
227         x1-= sima->zoom*sima->xof;
228         y1-= sima->zoom*sima->yof;
229         
230         /* relative display right */
231         sima->v2d.cur.xmin= ((curarea->winrct.xmin - (float)x1)/sima->zoom);
232         sima->v2d.cur.xmax= sima->v2d.cur.xmin + ((float)curarea->winx/sima->zoom);
233         
234         /* relative display left */
235         sima->v2d.cur.ymin= ((curarea->winrct.ymin-(float)y1)/sima->zoom);
236         sima->v2d.cur.ymax= sima->v2d.cur.ymin + ((float)curarea->winy/sima->zoom);
237         
238         if(mode=='f') {         
239                 sima->v2d.cur.xmin/= xim;
240                 sima->v2d.cur.xmax/= xim;
241                 sima->v2d.cur.ymin/= yim;
242                 sima->v2d.cur.ymax/= yim;
243         }
244 }
245
246 /* check for facelesect, and set active image */
247 void what_image(SpaceImage *sima)
248 {
249         if(             (sima->mode!=SI_TEXTURE) ||
250                         (sima->image && sima->image->source==IMA_SRC_VIEWER) ||
251                         (G.obedit != OBACT) ||
252                         (G.editMesh==NULL) ||
253                         (sima->pin)
254         ) {
255                 return;
256         }
257         
258         /* viewer overrides uv editmode */
259         if (EM_texFaceCheck()) {
260                 MTFace *activetf;
261                 
262                 sima->image= NULL;
263                 
264                 activetf = get_active_mtface(NULL, NULL, 1); /* partially selected face is ok */
265                 
266                 if(activetf && activetf->mode & TF_TEX) {
267                         /* done need to check for pin here, see above */
268                         /*if (!sima->pin)*/
269                         sima->image= activetf->tpage;
270                         
271                         if(sima->flag & SI_EDITTILE);
272                         else sima->curtile= activetf->tile;
273                         
274                         if(sima->image) {
275                                 if(activetf->mode & TF_TILES)
276                                         sima->image->tpageflag |= IMA_TILES;
277                                 else sima->image->tpageflag &= ~IMA_TILES;
278                         }
279                 }
280         }
281 }
282
283 /* after a what_image(), this call will give ibufs, includes the spare image */
284 ImBuf *imagewindow_get_ibuf(SpaceImage *sima)
285 {
286         if(G.sima->image) {
287                 /* check for spare */
288                 if(sima->image->type==IMA_TYPE_R_RESULT && BIF_show_render_spare())
289                         return BIF_render_spare_imbuf();
290                 else
291                         return BKE_image_get_ibuf(sima->image, &sima->iuser);
292         }
293         return NULL;
294 }
295
296 /*
297  * dotile -     1, set the tile flag (from the space image)
298  *                      2, set the tile index for the faces. 
299  * */
300 void image_set_tile(SpaceImage *sima, int dotile)
301 {
302         MTFace *tface;
303         EditMesh *em = G.editMesh;
304         EditFace *efa;
305         
306         if(!sima->image || sima->mode!=SI_TEXTURE || !EM_texFaceCheck())
307                 return;
308         
309         /* skip assigning these procedural images... */
310         if(sima->image && (sima->image->type==IMA_TYPE_R_RESULT || sima->image->type==IMA_TYPE_COMPOSITE))
311                 return;
312         
313         for (efa= em->faces.first; efa; efa= efa->next) {
314                 tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
315                 if (efa->h==0 && efa->f & SELECT) {
316                         if (dotile==1) {
317                                 /* set tile flag */
318                                 if (sima->image->tpageflag & IMA_TILES) {
319                                         tface->mode |= TF_TILES;
320                                 } else {
321                                         tface->mode &= ~TF_TILES;
322                                 }
323                         } else if (dotile==2) {
324                                 /* set tile index */
325                                 tface->tile= sima->curtile;
326                         }
327                 }
328         }
329         object_uvs_changed(OBACT);
330         allqueue(REDRAWBUTSEDIT, 0);
331 }
332
333
334
335 void uvco_to_areaco(float *vec, short *mval)
336 {
337         float x, y;
338
339         mval[0]= IS_CLIPPED;
340         
341         x= (vec[0] - G.v2d->cur.xmin)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
342         y= (vec[1] - G.v2d->cur.ymin)/(G.v2d->cur.ymax-G.v2d->cur.ymin);
343
344         if(x>=0.0 && x<=1.0) {
345                 if(y>=0.0 && y<=1.0) {          
346                         mval[0]= G.v2d->mask.xmin + x*(G.v2d->mask.xmax-G.v2d->mask.xmin);
347                         mval[1]= G.v2d->mask.ymin + y*(G.v2d->mask.ymax-G.v2d->mask.ymin);
348                 }
349         }
350 }
351
352 void uvco_to_areaco_noclip(float *vec, int *mval)
353 {
354         float x, y;
355
356         mval[0]= IS_CLIPPED;
357         
358         x= (vec[0] - G.v2d->cur.xmin)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
359         y= (vec[1] - G.v2d->cur.ymin)/(G.v2d->cur.ymax-G.v2d->cur.ymin);
360
361         x= G.v2d->mask.xmin + x*(G.v2d->mask.xmax-G.v2d->mask.xmin);
362         y= G.v2d->mask.ymin + y*(G.v2d->mask.ymax-G.v2d->mask.ymin);
363         
364         mval[0]= x;
365         mval[1]= y;
366 }
367
368 static void drawcursor_sima(float xuser_asp, float yuser_asp)
369 {
370         int wi, hi;
371         float w, h;
372         
373         if (    !G.obedit ||    /* only draw cursor in editmode */
374                         !CustomData_has_layer(&G.editMesh->fdata, CD_MTFACE) || /* must have UV's */
375                         (G.sima->image && G.sima->flag & SI_DRAWTOOL) /* cant be painting */
376                 )       return;
377         
378         transform_width_height_tface_uv(&wi, &hi);
379         w = (((float)wi)/256.0f)*G.sima->zoom * xuser_asp;
380         h = (((float)hi)/256.0f)*G.sima->zoom * yuser_asp;
381         
382         cpack(0xFFFFFF);
383         glTranslatef(G.v2d->cursor[0], G.v2d->cursor[1], 0.0f);  
384         fdrawline(-0.05/w, 0, 0, 0.05/h);
385         fdrawline(0, 0.05/h, 0.05/w, 0);
386         fdrawline(0.05/w, 0, 0, -0.05/h);
387         fdrawline(0, -0.05/h, -0.05/w, 0);
388         
389         setlinestyle(4);
390         cpack(0xFF);
391         fdrawline(-0.05/w, 0, 0, 0.05/h);
392         fdrawline(0, 0.05/h, 0.05/w, 0);
393         fdrawline(0.05/w, 0, 0, -0.05/h);
394         fdrawline(0, -0.05/h, -0.05/w, 0);
395         
396         
397         setlinestyle(0);
398         cpack(0x0);
399         fdrawline(-0.020/w, 0, -0.1/w, 0);
400         fdrawline(0.1/w, 0, .020/w, 0);
401         fdrawline(0, -0.020/h, 0, -0.1/h);
402         fdrawline(0, 0.1/h, 0, 0.020/h);
403         
404         setlinestyle(1);
405         cpack(0xFFFFFF);
406         fdrawline(-0.020/w, 0, -0.1/w, 0);
407         fdrawline(0.1/w, 0, .020/w, 0);
408         fdrawline(0, -0.020/h, 0, -0.1/h);
409         fdrawline(0, 0.1/h, 0, 0.020/h);
410         
411         glTranslatef(-G.v2d->cursor[0], -G.v2d->cursor[1], 0.0f);
412         setlinestyle(0);
413 }
414
415 // checks if we are selecting only faces
416 int draw_uvs_face_check(void)
417 {
418         if (G.sima==NULL) {
419                 return 0;
420         }
421         if (G.sima->flag & SI_SYNC_UVSEL) {
422                 if (G.scene->selectmode == SCE_SELECT_FACE) {
423                         return 2;
424                 } else if (G.scene->selectmode & SCE_SELECT_FACE) {
425                         return 1;
426                 } 
427         } else {
428                 if (G.sima->selectmode == SI_SELECT_FACE) {
429                         return 1;
430                 }
431         }
432         return 0;
433 }
434
435 void uv_center(float uv[][2], float cent[2], void * isquad)
436 {
437
438         if (isquad) {
439                 cent[0] = (uv[0][0] + uv[1][0] + uv[2][0] + uv[3][0]) / 4.0;
440                 cent[1] = (uv[0][1] + uv[1][1] + uv[2][1] + uv[3][1]) / 4.0;            
441         } else {
442                 cent[0] = (uv[0][0] + uv[1][0] + uv[2][0]) / 3.0;
443                 cent[1] = (uv[0][1] + uv[1][1] + uv[2][1]) / 3.0;               
444         }
445 }
446
447 static float uv_area(float uv[][2], int quad)
448 {
449         if (quad) {
450                 return AreaF2Dfl(uv[0], uv[1], uv[2]) + AreaF2Dfl(uv[0], uv[2], uv[3]); 
451         } else { 
452                 return AreaF2Dfl(uv[0], uv[1], uv[2]); 
453         }
454 }
455
456 void uv_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy)
457 {
458         uv[0][0] = uv_orig[0][0]*aspx;
459         uv[0][1] = uv_orig[0][1]*aspy;
460         
461         uv[1][0] = uv_orig[1][0]*aspx;
462         uv[1][1] = uv_orig[1][1]*aspy;
463         
464         uv[2][0] = uv_orig[2][0]*aspx;
465         uv[2][1] = uv_orig[2][1]*aspy;
466         
467         uv[3][0] = uv_orig[3][0]*aspx;
468         uv[3][1] = uv_orig[3][1]*aspy;
469 }
470
471 /* draws uv's in the image space */
472 void draw_uvs_sima(void)
473 {
474         MTFace *tface,*activetface = NULL;
475         EditMesh *em = G.editMesh;
476         EditFace *efa, *efa_act;
477         
478         char col1[4], col2[4];
479         float pointsize;
480         int drawface;
481         int lastsel, sel;
482         
483         if (!G.obedit || !CustomData_has_layer(&em->fdata, CD_MTFACE))
484                 return;
485         
486         drawface = draw_uvs_face_check();
487         
488         calc_image_view(G.sima, 'f');   /* float */
489         myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
490         glLoadIdentity();
491         
492         
493         if(G.sima->flag & SI_DRAWTOOL) {
494                 /* draws the grey mesh when painting */
495                 glColor3ub(112, 112, 112);
496                 for (efa= em->faces.first; efa; efa= efa->next) {
497                         tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
498                         glBegin(GL_LINE_LOOP);
499                         glVertex2fv(tface->uv[0]);
500                         glVertex2fv(tface->uv[1]);
501                         glVertex2fv(tface->uv[2]);
502                         if(efa->v4) glVertex2fv(tface->uv[3]);
503                         glEnd();
504                 }
505                 return; /* only draw shadow mesh */
506         } else if (G.sima->flag & SI_DRAWSHADOW) {
507                 /* draw shadow mesh - this is the mesh with the modifier applied */
508                 glColor3ub(112, 112, 112);
509                 if (    em->derivedFinal &&
510                                 em->derivedFinal->drawUVEdges &&
511                                 CustomData_has_layer(&em->derivedFinal->faceData, CD_MTFACE)
512                 ) {
513                         /* we can use the existing final mesh */
514                         glColor3ub(112, 112, 112);
515                         em->derivedFinal->drawUVEdges(em->derivedFinal);
516                 } else {
517                         DerivedMesh *finalDM, *cageDM;
518                         
519                         /* draw final mesh with modifiers applied */
520                         cageDM = editmesh_get_derived_cage_and_final(&finalDM, CD_MASK_BAREMESH | CD_MASK_MTFACE);
521                         
522                         if              (finalDM->drawUVEdges &&
523                                         DM_get_face_data_layer(finalDM, CD_MTFACE) &&
524                                         /* When sync selection is enabled, all faces are drawn (except for hidden)
525                                          * so if cage is the same as the final, theres no point in drawing the shadowmesh. */
526                                         !((G.sima->flag & SI_SYNC_UVSEL && cageDM==finalDM))
527                         ) {
528                                 glColor3ub(112, 112, 112);
529                                 finalDM->drawUVEdges(finalDM);
530                         }
531                         
532                         if (cageDM != finalDM)
533                                 cageDM->release(cageDM);
534                         finalDM->release(finalDM);
535                 }
536         }
537         
538         activetface = get_active_mtface(&efa_act, NULL, 0); /* will be set to NULL if hidden */
539                 
540         
541         if (G.sima->flag & SI_DRAW_STRETCH) {
542                 float col[4];
543                 float aspx, aspy;
544                 float tface_uv[4][2];
545                 
546                 transform_aspect_ratio_tface_uv(&aspx, &aspy);
547                 
548                 switch (G.sima->dt_uvstretch) {
549                         case SI_UVDT_STRETCH_AREA:
550                         {
551                                 float totarea=0.0f, totuvarea=0.0f, areadiff, uvarea, area;
552                                 
553                                 for (efa= em->faces.first; efa; efa= efa->next) {
554                                         tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
555                                         uv_copy_aspect(tface->uv, tface_uv, aspx, aspy);
556
557                                         totarea += EM_face_area(efa);
558                                         //totuvarea += tface_area(tface, efa->v4!=0);
559                                         totuvarea += uv_area(tface_uv, efa->v4!=0);
560                                         
561                                         if (simaFaceDraw_Check(efa, tface)) {
562                                                 efa->tmp.p = tface;
563                                         } else {
564                                                 if (tface == activetface)
565                                                         activetface= NULL;
566                                                 efa->tmp.p = NULL;
567                                         }
568                                 }
569                                 
570                                 if (totarea < FLT_EPSILON || totuvarea < FLT_EPSILON) {
571                                         col[0] = 1.0;
572                                         col[1] = col[2] = 0.0;
573                                         glColor3fv(col);
574                                         for (efa= em->faces.first; efa; efa= efa->next) {
575                                                 if ((tface=(MTFace *)efa->tmp.p)) {
576                                                         glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
577                                                                 glVertex2fv(tface->uv[0]);
578                                                                 glVertex2fv(tface->uv[1]);
579                                                                 glVertex2fv(tface->uv[2]);
580                                                                 if(efa->v4) glVertex2fv(tface->uv[3]);
581                                                         glEnd();
582                                                 }
583                                         }
584                                 } else {
585                                         for (efa= em->faces.first; efa; efa= efa->next) {
586                                                 if ((tface=(MTFace *)efa->tmp.p)) {
587                                                         area = EM_face_area(efa) / totarea;
588                                                         uv_copy_aspect(tface->uv, tface_uv, aspx, aspy);
589                                                         //uvarea = tface_area(tface, efa->v4!=0) / totuvarea;
590                                                         uvarea = uv_area(tface_uv, efa->v4!=0) / totuvarea;
591                                                         
592                                                         if (area < FLT_EPSILON || uvarea < FLT_EPSILON) {
593                                                                 areadiff = 1.0;
594                                                         } else if (area>uvarea) {
595                                                                 areadiff = 1.0-(uvarea/area);
596                                                         } else {
597                                                                 areadiff = 1.0-(area/uvarea);
598                                                         }
599                                                         
600                                                         weight_to_rgb(areadiff, col, col+1, col+2);
601                                                         glColor3fv(col);
602                                                         
603                                                         glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
604                                                                 glVertex2fv(tface->uv[0]);
605                                                                 glVertex2fv(tface->uv[1]);
606                                                                 glVertex2fv(tface->uv[2]);
607                                                                 if(efa->v4) glVertex2fv(tface->uv[3]);
608                                                         glEnd();
609                                                 }
610                                         }
611                                 }
612                                 break;
613                         }
614                         case SI_UVDT_STRETCH_ANGLE:
615                         {
616                                 float uvang1,uvang2,uvang3,uvang4;
617                                 float ang1,ang2,ang3,ang4;
618                                 float av1[3], av2[3], av3[3], av4[3]; /* use for 2d and 3d  angle vectors */
619                                 float a;
620                                 
621                                 col[3] = 0.5; /* hard coded alpha, not that nice */
622                                 
623                                 glShadeModel(GL_SMOOTH);
624                                 
625                                 for (efa= em->faces.first; efa; efa= efa->next) {
626                                         tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
627                                         
628                                         if (simaFaceDraw_Check(efa, tface)) {
629                                                 efa->tmp.p = tface;
630                                                 uv_copy_aspect(tface->uv, tface_uv, aspx, aspy);
631                                                 if (efa->v4) {
632                                                         
633 #if 0                                           /* Simple but slow, better reuse normalized vectors */
634                                                         uvang1 = VecAngle3_2D(tface_uv[3], tface_uv[0], tface_uv[1]);
635                                                         ang1 = VecAngle3(efa->v4->co, efa->v1->co, efa->v2->co);
636                                                         
637                                                         uvang2 = VecAngle3_2D(tface_uv[0], tface_uv[1], tface_uv[2]);
638                                                         ang2 = VecAngle3(efa->v1->co, efa->v2->co, efa->v3->co);
639                                                         
640                                                         uvang3 = VecAngle3_2D(tface_uv[1], tface_uv[2], tface_uv[3]);
641                                                         ang3 = VecAngle3(efa->v2->co, efa->v3->co, efa->v4->co);
642                                                         
643                                                         uvang4 = VecAngle3_2D(tface_uv[2], tface_uv[3], tface_uv[0]);
644                                                         ang4 = VecAngle3(efa->v3->co, efa->v4->co, efa->v1->co);
645 #endif
646                                                         
647                                                         /* uv angles */
648                                                         VECSUB2D(av1, tface_uv[3], tface_uv[0]); Normalize2(av1);
649                                                         VECSUB2D(av2, tface_uv[0], tface_uv[1]); Normalize2(av2);
650                                                         VECSUB2D(av3, tface_uv[1], tface_uv[2]); Normalize2(av3);
651                                                         VECSUB2D(av4, tface_uv[2], tface_uv[3]); Normalize2(av4);
652                                                         
653                                                         /* This is the correct angle however we are only comparing angles
654                                                          * uvang1 = 90-((NormalizedVecAngle2_2D(av1, av2) * 180.0/M_PI)-90);*/
655                                                         uvang1 = NormalizedVecAngle2_2D(av1, av2)*180.0/M_PI;
656                                                         uvang2 = NormalizedVecAngle2_2D(av2, av3)*180.0/M_PI;
657                                                         uvang3 = NormalizedVecAngle2_2D(av3, av4)*180.0/M_PI;
658                                                         uvang4 = NormalizedVecAngle2_2D(av4, av1)*180.0/M_PI;
659                                                         
660                                                         /* 3d angles */
661                                                         VECSUB(av1, efa->v4->co, efa->v1->co); Normalize(av1);
662                                                         VECSUB(av2, efa->v1->co, efa->v2->co); Normalize(av2);
663                                                         VECSUB(av3, efa->v2->co, efa->v3->co); Normalize(av3);
664                                                         VECSUB(av4, efa->v3->co, efa->v4->co); Normalize(av4);
665                                                         
666                                                         /* This is the correct angle however we are only comparing angles
667                                                          * ang1 = 90-((NormalizedVecAngle2(av1, av2) * 180.0/M_PI)-90);*/
668                                                         ang1 = NormalizedVecAngle2(av1, av2)*180.0/M_PI;
669                                                         ang2 = NormalizedVecAngle2(av2, av3)*180.0/M_PI;
670                                                         ang3 = NormalizedVecAngle2(av3, av4)*180.0/M_PI;
671                                                         ang4 = NormalizedVecAngle2(av4, av1)*180.0/M_PI;
672                                                         
673                                                         glBegin(GL_QUADS);
674                                                         
675                                                         /* This simple makes the angles display worse then they really are ;)
676                                                          * 1.0-pow((1.0-a), 2) */
677                                                         
678                                                         a = fabs(uvang1-ang1)/180.0;
679                                                         weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
680                                                         glColor3fv(col);
681                                                         glVertex2fv(tface->uv[0]);
682                                                         a = fabs(uvang2-ang2)/180.0;
683                                                         weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
684                                                         glColor3fv(col);
685                                                         glVertex2fv(tface->uv[1]);
686                                                         a = fabs(uvang3-ang3)/180.0;
687                                                         weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
688                                                         glColor3fv(col);
689                                                         glVertex2fv(tface->uv[2]);
690                                                         a = fabs(uvang4-ang4)/180.0;
691                                                         weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
692                                                         glColor3fv(col);
693                                                         glVertex2fv(tface->uv[3]);
694                                                         
695                                                 } else {
696 #if 0                                           /* Simple but slow, better reuse normalized vectors */
697                                                         uvang1 = VecAngle3_2D(tface_uv[2], tface_uv[0], tface_uv[1]);
698                                                         ang1 = VecAngle3(efa->v3->co, efa->v1->co, efa->v2->co);
699                                                         
700                                                         uvang2 = VecAngle3_2D(tface_uv[0], tface_uv[1], tface_uv[2]);
701                                                         ang2 = VecAngle3(efa->v1->co, efa->v2->co, efa->v3->co);
702                                                         
703                                                         uvang3 = 180-(uvang1+uvang2);
704                                                         ang3 = 180-(ang1+ang2);
705 #endif                                          
706                                                         
707                                                         /* uv angles */
708                                                         VECSUB2D(av1, tface_uv[2], tface_uv[0]); Normalize2(av1);
709                                                         VECSUB2D(av2, tface_uv[0], tface_uv[1]); Normalize2(av2);
710                                                         VECSUB2D(av3, tface_uv[1], tface_uv[2]); Normalize2(av3);
711                                                         
712                                                         /* This is the correct angle however we are only comparing angles
713                                                          * uvang1 = 90-((NormalizedVecAngle2_2D(av1, av2) * 180.0/M_PI)-90); */
714                                                         uvang1 = NormalizedVecAngle2_2D(av1, av2)*180.0/M_PI;
715                                                         uvang2 = NormalizedVecAngle2_2D(av2, av3)*180.0/M_PI;
716                                                         uvang3 = NormalizedVecAngle2_2D(av3, av1)*180.0/M_PI;
717                                                         
718                                                         /* 3d angles */
719                                                         VECSUB(av1, efa->v3->co, efa->v1->co); Normalize(av1);
720                                                         VECSUB(av2, efa->v1->co, efa->v2->co); Normalize(av2);
721                                                         VECSUB(av3, efa->v2->co, efa->v3->co); Normalize(av3);
722                                                         /* This is the correct angle however we are only comparing angles
723                                                          * ang1 = 90-((NormalizedVecAngle2(av1, av2) * 180.0/M_PI)-90); */
724                                                         ang1 = NormalizedVecAngle2(av1, av2)*180.0/M_PI;
725                                                         ang2 = NormalizedVecAngle2(av2, av3)*180.0/M_PI;
726                                                         ang3 = NormalizedVecAngle2(av3, av1)*180.0/M_PI;
727                                                         
728                                                         /* This simple makes the angles display worse then they really are ;)
729                                                          * 1.0-pow((1.0-a), 2) */
730                                                         
731                                                         glBegin(GL_TRIANGLES);
732                                                         a = fabs(uvang1-ang1)/180.0;
733                                                         weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
734                                                         glColor3fv(col);
735                                                         glVertex2fv(tface->uv[0]);
736                                                         a = fabs(uvang2-ang2)/180.0;
737                                                         weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
738                                                         glColor3fv(col);
739                                                         glVertex2fv(tface->uv[1]);
740                                                         a = fabs(uvang3-ang3)/180.0;
741                                                         weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
742                                                         glColor3fv(col);
743                                                         glVertex2fv(tface->uv[2]);
744                                                 }
745                                                 glEnd();
746                                         } else {
747                                                 if (tface == activetface)
748                                                         activetface= NULL;
749                                                 efa->tmp.p = NULL;
750                                         }
751                                 }
752                                 glShadeModel(GL_FLAT);
753                                 break;
754                         }
755                 }
756         } else if(G.f & G_DRAWFACES) {
757                 /* draw transparent faces */
758                 BIF_GetThemeColor4ubv(TH_FACE, col1);
759                 BIF_GetThemeColor4ubv(TH_FACE_SELECT, col2);
760                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
761                 glEnable(GL_BLEND);
762                 
763                 for (efa= em->faces.first; efa; efa= efa->next) {
764                         tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
765                         
766                         if (simaFaceDraw_Check(efa, tface)) {
767                                 efa->tmp.p = tface;
768                                 if (tface==activetface) continue; /* important the temp pointer is set above */
769                                 if( simaFaceSel_Check(efa, tface)) {
770                                         glColor4ubv((GLubyte *)col2);
771                                 } else {
772                                         glColor4ubv((GLubyte *)col1);
773                                 }
774                                         
775                                 glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
776                                         glVertex2fv(tface->uv[0]);
777                                         glVertex2fv(tface->uv[1]);
778                                         glVertex2fv(tface->uv[2]);
779                                         if(efa->v4) glVertex2fv(tface->uv[3]);
780                                 glEnd();
781                                 
782                         } else {
783                                 if (tface == activetface)
784                                         activetface= NULL;
785                                 efa->tmp.p = NULL;
786                         }
787                 }
788                 glDisable(GL_BLEND);
789         } else {
790                 /* would be nice to do this within a draw loop but most below are optional, so it would involve too many checks */
791                 for (efa= em->faces.first; efa; efa= efa->next) {
792                         tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
793                         if (simaFaceDraw_Check(efa, tface)) {           
794                                 efa->tmp.p = tface;
795                         } else {
796                                 if (tface == activetface)
797                                         activetface= NULL;
798                                 efa->tmp.p = NULL;
799                         }
800                 }
801                 
802         }
803         
804         if (activetface) {
805                 glEnable(GL_BLEND);
806                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
807                 BIF_ThemeColor4(TH_EDITMESH_ACTIVE);
808                 glEnable(GL_POLYGON_STIPPLE);
809                 glPolygonStipple(stipple_quarttone);
810                 glBegin(efa_act->v4?GL_QUADS:GL_TRIANGLES);
811                         glVertex2fv(activetface->uv[0]);
812                         glVertex2fv(activetface->uv[1]);
813                         glVertex2fv(activetface->uv[2]);
814                         if(efa_act->v4) glVertex2fv(activetface->uv[3]);
815                 glEnd();
816                 glDisable(GL_POLYGON_STIPPLE);
817                 glDisable(GL_BLEND);
818         }
819         
820         if (G.sima->flag & SI_SMOOTH_UV) {
821                 glEnable( GL_LINE_SMOOTH );
822                 glEnable(GL_BLEND);
823                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
824         }
825         
826         switch (G.sima->dt_uv) {
827         case SI_UVDT_DASH:
828                 for (efa= em->faces.first; efa; efa= efa->next) {
829 //                      tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
830 //                      if (simaFaceDraw_Check(efa, tface)) {
831                         
832                         /*this is a shortcut to do the same as above but a faster for drawing */
833                         if ((tface=(MTFace *)efa->tmp.p)) {
834                         
835                                 cpack(0x111111);
836                                 glBegin(GL_LINE_LOOP);
837                                         glVertex2fv(tface->uv[0]);
838                                         glVertex2fv(tface->uv[1]);
839                                         glVertex2fv(tface->uv[2]);
840                                         if(efa->v4) glVertex2fv(tface->uv[3]);
841                                 glEnd();
842                         
843                                 setlinestyle(2);
844                                 cpack(0x909090);
845                                 glBegin(GL_LINE_STRIP);
846                                         glVertex2fv(tface->uv[0]);
847                                         glVertex2fv(tface->uv[1]);
848                                 glEnd();
849         
850                                 glBegin(GL_LINE_STRIP);
851                                         glVertex2fv(tface->uv[0]);
852                                         if(efa->v4) glVertex2fv(tface->uv[3]);
853                                         else glVertex2fv(tface->uv[2]);
854                                 glEnd();
855         
856                                 glBegin(GL_LINE_STRIP);
857                                         glVertex2fv(tface->uv[1]);
858                                         glVertex2fv(tface->uv[2]);
859                                         if(efa->v4) glVertex2fv(tface->uv[3]);
860                                 glEnd();
861                                 setlinestyle(0);
862                         }
863                 }
864                 break;
865         case SI_UVDT_BLACK: /* black/white */
866         case SI_UVDT_WHITE: 
867                 cpack((G.sima->dt_uv==SI_UVDT_WHITE) ? 0xFFFFFF : 0x0);
868                 for (efa= em->faces.first; efa; efa= efa->next) {
869 //                      tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
870 //                      if (simaFaceDraw_Check(efa, tface)) {
871                         
872                         /*this is a shortcut to do the same as above but a faster for drawing */
873                         if ((tface=(MTFace *)efa->tmp.p)) {
874                         
875                                 glBegin(GL_LINE_LOOP);
876                                         glVertex2fv(tface->uv[0]);
877                                         glVertex2fv(tface->uv[1]);
878                                         glVertex2fv(tface->uv[2]);
879                                         if(efa->v4) glVertex2fv(tface->uv[3]);
880                                 glEnd();
881                         }
882                 }
883                 break;
884         case SI_UVDT_OUTLINE:
885                 glLineWidth(3);
886                 cpack(0x0);
887                 
888                 for (efa= em->faces.first; efa; efa= efa->next) {
889 //                      tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
890 //                      if (simaFaceDraw_Check(efa, tface)) {
891                         
892                         /*this is a shortcut to do the same as above but a faster for drawing */
893                         if ((tface=(MTFace *)efa->tmp.p)) {
894                                 
895                                 glBegin(GL_LINE_LOOP);
896                                         glVertex2fv(tface->uv[0]);
897                                         glVertex2fv(tface->uv[1]);
898                                         glVertex2fv(tface->uv[2]);
899                                         if(efa->v4) glVertex2fv(tface->uv[3]);
900                                 glEnd();
901                         }
902                 }
903                 
904                 glLineWidth(1);
905                 col2[0] = col2[1] = col2[2] = 128; col2[3] = 255;
906                 glColor4ubv((unsigned char *)col2); 
907                 
908                 if (G.f & G_DRAWEDGES) {
909                         glShadeModel(GL_SMOOTH);
910                         BIF_GetThemeColor4ubv(TH_VERTEX_SELECT, col1);
911                         lastsel = sel = 0;
912
913                         for (efa= em->faces.first; efa; efa= efa->next) {
914         //                      tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
915         //                      if (simaFaceDraw_Check(efa, tface)) {
916                                 
917                                 /*this is a shortcut to do the same as above but a faster for drawing */
918                                 if ((tface=(MTFace *)efa->tmp.p)) {
919                                         
920                                         glBegin(GL_LINE_LOOP);
921                                         sel = (simaUVSel_Check(efa, tface, 0) ? 1 : 0);
922                                         if (sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
923                                         glVertex2fv(tface->uv[0]);
924                                         
925                                         sel = simaUVSel_Check(efa, tface, 1) ? 1 : 0;
926                                         if (sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
927                                         glVertex2fv(tface->uv[1]);
928                                         
929                                         sel = simaUVSel_Check(efa, tface, 2) ? 1 : 0;
930                                         if (sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
931                                         glVertex2fv(tface->uv[2]);
932                                         
933                                         if(efa->v4) {
934                                                 sel = simaUVSel_Check(efa, tface, 3) ? 1 : 0;
935                                                 if (sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
936                                                 glVertex2fv(tface->uv[3]);
937                                         }
938                                         
939                                         glEnd();
940                                 }
941                         }
942                         glShadeModel(GL_FLAT);
943                 } else { /* No nice edges */
944                         
945                         for (efa= em->faces.first; efa; efa= efa->next) {
946         //                      tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
947         //                      if (simaFaceDraw_Check(efa, tface)) {
948                                 
949                                 /*this is a shortcut to do the same as above but a faster for drawing */
950                                 if ((tface=(MTFace *)efa->tmp.p)) {
951                                         
952                                         glBegin(GL_LINE_LOOP);
953                                         glVertex2fv(tface->uv[0]);
954                                         glVertex2fv(tface->uv[1]);
955                                         glVertex2fv(tface->uv[2]);
956                                         if(efa->v4)
957                                                 glVertex2fv(tface->uv[3]);
958                                         glEnd();
959                                 }
960                         }
961                 }
962                 
963                 break;
964         }
965
966         if (G.sima->flag & SI_SMOOTH_UV) {
967                 glDisable( GL_LINE_SMOOTH);
968                 glDisable(GL_BLEND);
969         }
970
971         if (drawface) {
972                 // draw UV face points
973                 float cent[2];
974                 
975                 
976             /* unselected faces's */
977                 pointsize = BIF_GetThemeValuef(TH_FACEDOT_SIZE);
978                 // TODO - drawobject.c changes this value after - Investiagate!
979                 glPointSize(pointsize);
980                 
981                 BIF_ThemeColor(TH_WIRE);
982                 bglBegin(GL_POINTS);
983                 for (efa= em->faces.first; efa; efa= efa->next) {
984                         
985 //                      tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
986 //                      if (simaFaceDraw_Check(efa, tface)) {
987                         
988                         /*this is a shortcut to do the same as above but a faster for drawing */
989                         if ((tface=(MTFace *)efa->tmp.p)) {
990                                 if( ! simaFaceSel_Check(efa, tface) ) {
991                                         uv_center(tface->uv, cent, (void *)efa->v4);
992                                         bglVertex2fv(cent);
993                                 }
994                         }
995                 }
996                 bglEnd();
997                 /* selected faces's */
998                 BIF_ThemeColor(TH_FACE_DOT);
999                 bglBegin(GL_POINTS);
1000                 for (efa= em->faces.first; efa; efa= efa->next) {
1001                         
1002 //                      tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1003 //                      if (simaFaceDraw_Check(efa, tface)) {
1004                         
1005                         /*this is a shortcut to do the same as above but a faster for drawing */
1006                         if ((tface=(MTFace *)efa->tmp.p)) {
1007                                 if( simaFaceSel_Check(efa, tface) ) {
1008                                         uv_center(tface->uv, cent, (void *)efa->v4);
1009                                         bglVertex2fv(cent);
1010                                 }
1011                         }
1012                 }
1013                 bglEnd();
1014         }
1015         
1016         if (drawface != 2) { /* 2 means Mesh Face Mode */
1017             /* unselected uv's */
1018                 BIF_ThemeColor(TH_VERTEX);
1019                 pointsize = BIF_GetThemeValuef(TH_VERTEX_SIZE);
1020                 glPointSize(pointsize);
1021         
1022                 bglBegin(GL_POINTS);
1023                 for (efa= em->faces.first; efa; efa= efa->next) {
1024                         
1025 //                      tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1026 //                      if (simaFaceDraw_Check(efa, tface)) {
1027                         
1028                         /*this is a shortcut to do the same as above but a faster for drawing */
1029                         if ((tface=(MTFace *)efa->tmp.p)) {
1030                         
1031                                 if(simaUVSel_Check(efa, tface, 0)); else bglVertex2fv(tface->uv[0]);
1032                                 if(simaUVSel_Check(efa, tface, 1)); else bglVertex2fv(tface->uv[1]);
1033                                 if(simaUVSel_Check(efa, tface, 2)); else bglVertex2fv(tface->uv[2]);
1034                                 if(efa->v4) {
1035                                         if(simaUVSel_Check(efa, tface, 3)); else bglVertex2fv(tface->uv[3]);
1036                                 }
1037                         }
1038                 }
1039                 bglEnd();
1040         
1041                 /* pinned uv's */
1042                 /* give odd pointsizes odd pin pointsizes */
1043             glPointSize(pointsize*2 + (((int)pointsize % 2)? (-1): 0));
1044                 cpack(0xFF);
1045         
1046                 bglBegin(GL_POINTS);
1047                 for (efa= em->faces.first; efa; efa= efa->next) {
1048 //                      tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1049 //                      if (simaFaceDraw_Check(efa, tface)) {
1050                         
1051                         /*this is a shortcut to do the same as above but a faster for drawing */
1052                         if ((tface=(MTFace *)efa->tmp.p)) {
1053                                 
1054                                 if(tface->unwrap & TF_PIN1) bglVertex2fv(tface->uv[0]);
1055                                 if(tface->unwrap & TF_PIN2) bglVertex2fv(tface->uv[1]);
1056                                 if(tface->unwrap & TF_PIN3) bglVertex2fv(tface->uv[2]);
1057                                 if(efa->v4) {
1058                                         if(tface->unwrap & TF_PIN4) bglVertex2fv(tface->uv[3]);
1059                                 }
1060                         }
1061                 }
1062                 bglEnd();
1063         
1064                 /* selected uv's */
1065                 BIF_ThemeColor(TH_VERTEX_SELECT);
1066             glPointSize(pointsize);
1067         
1068                 bglBegin(GL_POINTS);
1069                 for (efa= em->faces.first; efa; efa= efa->next) {
1070 //                      tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1071 //                      if (simaFaceDraw_Check(efa, tface)) {
1072                         
1073                         /*this is a shortcut to do the same as above but a faster for drawing */
1074                         if ((tface=(MTFace *)efa->tmp.p)) {
1075                         
1076                                 if(!simaUVSel_Check(efa, tface, 0)); else bglVertex2fv(tface->uv[0]);
1077                                 if(!simaUVSel_Check(efa, tface, 1)); else bglVertex2fv(tface->uv[1]);
1078                                 if(!simaUVSel_Check(efa, tface, 2)); else bglVertex2fv(tface->uv[2]);
1079                                 if(efa->v4) {
1080                                         if(!simaUVSel_Check(efa, tface, 3)); else bglVertex2fv(tface->uv[3]);
1081                                 }
1082                         }
1083                 }
1084                 bglEnd();       
1085         }
1086         glPointSize(1.0);
1087 }
1088
1089 static unsigned int *get_part_from_ibuf(ImBuf *ibuf, short startx, short starty, short endx, short endy)
1090 {
1091         unsigned int *rt, *rp, *rectmain;
1092         short y, heigth, len;
1093
1094         /* the right offset in rectot */
1095
1096         rt= ibuf->rect+ (starty*ibuf->x+ startx);
1097
1098         len= (endx-startx);
1099         heigth= (endy-starty);
1100
1101         rp=rectmain= MEM_mallocN(heigth*len*sizeof(int), "rect");
1102         
1103         for(y=0; y<heigth; y++) {
1104                 memcpy(rp, rt, len*4);
1105                 rt+= ibuf->x;
1106                 rp+= len;
1107         }
1108         return rectmain;
1109 }
1110
1111 static void draw_image_transform(ImBuf *ibuf, float xuser_asp, float yuser_asp)
1112 {
1113         if(G.moving) {
1114                 float aspx, aspy, center[3];
1115
1116         BIF_drawConstraint();
1117
1118                 if(ibuf==0 || ibuf->rect==0 || ibuf->x==0 || ibuf->y==0) {
1119                         aspx= aspy= 1.0;
1120                 }
1121                 else {
1122                         aspx= (256.0/ibuf->x) * xuser_asp;
1123                         aspy= (256.0/ibuf->y) * yuser_asp;
1124                 }
1125                 BIF_getPropCenter(center);
1126
1127                 /* scale and translate the circle into place and draw it */
1128                 glPushMatrix();
1129                 glScalef(aspx, aspy, 1.0);
1130                 glTranslatef((1/aspx)*center[0] - center[0],
1131                              (1/aspy)*center[1] - center[1], 0.0);
1132
1133                 BIF_drawPropCircle();
1134
1135                 glPopMatrix();
1136         }
1137 }
1138
1139 static void draw_image_view_tool(void)
1140 {
1141         ToolSettings *settings= G.scene->toolsettings;
1142         Brush *brush= settings->imapaint.brush;
1143         short mval[2];
1144         float radius;
1145         int draw= 0;
1146
1147         if(brush) {
1148                 if(settings->imapaint.flag & IMAGEPAINT_DRAWING) {
1149                         if(settings->imapaint.flag & IMAGEPAINT_DRAW_TOOL_DRAWING)
1150                                 draw= 1;
1151                 }
1152                 else if(settings->imapaint.flag & IMAGEPAINT_DRAW_TOOL)
1153                         draw= 1;
1154                 
1155                 if(draw) {
1156                         getmouseco_areawin(mval);
1157
1158                         radius= brush->size*G.sima->zoom/2;
1159                         fdrawXORcirc(mval[0], mval[1], radius);
1160
1161                         if (brush->innerradius != 1.0) {
1162                                 radius *= brush->innerradius;
1163                                 fdrawXORcirc(mval[0], mval[1], radius);
1164                         }
1165                 }
1166         }
1167 }
1168
1169 /* ************ panel stuff ************* */
1170
1171 /* this function gets the values for cursor and vertex number buttons */
1172 static void image_transform_but_attr(int *imx, int *imy, int *step, int *digits) /*, float *xcoord, float *ycoord)*/
1173 {
1174         ImBuf *ibuf= imagewindow_get_ibuf(G.sima);
1175         if(ibuf) {
1176                 *imx= ibuf->x;
1177                 *imy= ibuf->y;
1178         }
1179         
1180         if (G.sima->flag & SI_COORDFLOATS) {
1181                 *step= 1;
1182                 *digits= 3;
1183         }
1184         else {
1185                 *step= 100;
1186                 *digits= 2;
1187         }
1188 }
1189
1190
1191 /* is used for both read and write... */
1192 void image_editvertex_buts(uiBlock *block)
1193 {
1194         static float ocent[2];
1195         float cent[2]= {0.0, 0.0};
1196         int imx= 256, imy= 256;
1197         int nactive= 0, step, digits;
1198         EditMesh *em = G.editMesh;
1199         EditFace *efa;
1200         MTFace *tf;
1201         
1202         if( is_uv_tface_editing_allowed_silent()==0 ) return;
1203         
1204         image_transform_but_attr(&imx, &imy, &step, &digits);
1205         
1206         for (efa= em->faces.first; efa; efa= efa->next) {
1207                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1208                 if (simaFaceDraw_Check(efa, tf)) {
1209                         
1210                         if (simaUVSel_Check(efa, tf, 0)) {
1211                                 cent[0]+= tf->uv[0][0];
1212                                 cent[1]+= tf->uv[0][1];
1213                                 nactive++;
1214                         }
1215                         if (simaUVSel_Check(efa, tf, 1)) {
1216                                 cent[0]+= tf->uv[1][0];
1217                                 cent[1]+= tf->uv[1][1];
1218                                 nactive++;
1219                         }
1220                         if (simaUVSel_Check(efa, tf, 2)) {
1221                                 cent[0]+= tf->uv[2][0];
1222                                 cent[1]+= tf->uv[2][1];
1223                                 nactive++;
1224                         }
1225                         if (efa->v4 && simaUVSel_Check(efa, tf, 3)) {
1226                                 cent[0]+= tf->uv[3][0];
1227                                 cent[1]+= tf->uv[3][1];
1228                                 nactive++;
1229                         }
1230                 }
1231         }
1232                 
1233         if(block) {     // do the buttons
1234                 if (nactive) {
1235                         ocent[0]= cent[0]/nactive;
1236                         ocent[1]= cent[1]/nactive;
1237                         if (G.sima->flag & SI_COORDFLOATS) {
1238                         } else {
1239                                 ocent[0] *= imx;
1240                                 ocent[1] *= imy;
1241                         }
1242                         
1243                         //uiBlockBeginAlign(block);
1244                         if(nactive==1) {
1245                                 uiDefButF(block, NUM, B_TRANS_IMAGE, "Vertex X:",       10, 10, 145, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, "");
1246                                 uiDefButF(block, NUM, B_TRANS_IMAGE, "Vertex Y:",       165, 10, 145, 19, &ocent[1], -10*imy, 10.0*imy, step, digits, "");
1247                         }
1248                         else {
1249                                 uiDefButF(block, NUM, B_TRANS_IMAGE, "Median X:",       10, 10, 145, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, "");
1250                                 uiDefButF(block, NUM, B_TRANS_IMAGE, "Median Y:",       165, 10, 145, 19, &ocent[1], -10*imy, 10.0*imy, step, digits, "");
1251                         }
1252                         //uiBlockEndAlign(block);
1253                 }
1254         }
1255         else {  // apply event
1256                 float delta[2];
1257                 
1258                 cent[0]= cent[0]/nactive;
1259                 cent[1]= cent[1]/nactive;
1260                         
1261                 if (G.sima->flag & SI_COORDFLOATS) {
1262                         delta[0]= ocent[0]-cent[0];
1263                         delta[1]= ocent[1]-cent[1];
1264                 }
1265                 else {
1266                         delta[0]= ocent[0]/imx - cent[0];
1267                         delta[1]= ocent[1]/imy - cent[1];
1268                 }
1269
1270                 for (efa= em->faces.first; efa; efa= efa->next) {
1271                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1272                         if (simaFaceDraw_Check(efa, tf)) {
1273                                 if (simaUVSel_Check(efa, tf, 0)) {
1274                                         tf->uv[0][0]+= delta[0];
1275                                         tf->uv[0][1]+= delta[1];
1276                                 }
1277                                 if (simaUVSel_Check(efa, tf, 1)) {
1278                                         tf->uv[1][0]+= delta[0];
1279                                         tf->uv[1][1]+= delta[1];
1280                                 }
1281                                 if (simaUVSel_Check(efa, tf, 2)) {
1282                                         tf->uv[2][0]+= delta[0];
1283                                         tf->uv[2][1]+= delta[1];
1284                                 }
1285                                 if (efa->v4 && simaUVSel_Check(efa, tf, 3)) {
1286                                         tf->uv[3][0]+= delta[0];
1287                                         tf->uv[3][1]+= delta[1];
1288                                 }
1289                         }
1290                 }
1291                         
1292                 allqueue(REDRAWVIEW3D, 0);
1293                 allqueue(REDRAWIMAGE, 0);
1294         }
1295 }
1296
1297
1298 /* is used for both read and write... */
1299 void image_editcursor_buts(uiBlock *block)
1300 {
1301         static float ocent[2];
1302         int imx= 256, imy= 256;
1303         int step, digits;
1304         
1305         if( is_uv_tface_editing_allowed_silent()==0 ) return;
1306         
1307         image_transform_but_attr(&imx, &imy, &step, &digits);
1308                 
1309         if(block) {     // do the buttons
1310                 ocent[0]= G.v2d->cursor[0];
1311                 ocent[1]= G.v2d->cursor[1];
1312                 if (G.sima->flag & SI_COORDFLOATS) {
1313                 } else {
1314                         ocent[0] *= imx;
1315                         ocent[1] *= imy;
1316                 }
1317                 
1318                 uiBlockBeginAlign(block);
1319                 uiDefButF(block, NUM, B_CURSOR_IMAGE, "Cursor X:",      165, 120, 145, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, "");
1320                 uiDefButF(block, NUM, B_CURSOR_IMAGE, "Cursor Y:",      165, 100, 145, 19, &ocent[1], -10*imy, 10.0*imy, step, digits, "");
1321                 uiBlockEndAlign(block);
1322         }
1323         else {  // apply event
1324                 if (G.sima->flag & SI_COORDFLOATS) {
1325                         G.v2d->cursor[0]= ocent[0];
1326                         G.v2d->cursor[1]= ocent[1];
1327                 }
1328                 else {
1329                         G.v2d->cursor[0]= ocent[0]/imx;
1330                         G.v2d->cursor[1]= ocent[1]/imy;
1331                 }
1332                 allqueue(REDRAWIMAGE, 0);
1333         }
1334 }
1335
1336
1337 void image_info(Image *ima, ImBuf *ibuf, char *str)
1338 {
1339         int ofs= 0;
1340         
1341         str[0]= 0;
1342         
1343         if(ima==NULL) return;
1344         if(ibuf==NULL) {
1345                 sprintf(str, "Can not get an image");
1346                 return;
1347         }
1348         
1349         if(ima->source==IMA_SRC_MOVIE) {
1350                 ofs= sprintf(str, "Movie ");
1351                 if(ima->anim) 
1352                         ofs+= sprintf(str+ofs, "%d frs", IMB_anim_get_duration(ima->anim));
1353         }
1354         else
1355                 ofs= sprintf(str, "Image ");
1356
1357         ofs+= sprintf(str+ofs, ": size %d x %d,", ibuf->x, ibuf->y);
1358         
1359         if(ibuf->rect_float) {
1360                 if(ibuf->channels!=4) {
1361                         sprintf(str+ofs, "%d float channel(s)", ibuf->channels);
1362                 }
1363                 else if(ibuf->depth==32)
1364                         strcat(str, " RGBA float");
1365                 else
1366                         strcat(str, " RGB float");
1367         }
1368         else {
1369                 if(ibuf->depth==32)
1370                         strcat(str, " RGBA byte");
1371                 else
1372                         strcat(str, " RGB byte");
1373         }
1374         if(ibuf->zbuf || ibuf->zbuf_float)
1375                 strcat(str, " + Z");
1376         
1377 }
1378
1379 static void image_panel_properties(short cntrl) // IMAGE_HANDLER_PROPERTIES
1380 {
1381         uiBlock *block;
1382         
1383         block= uiNewBlock(&curarea->uiblocks, "image_panel_properties", UI_EMBOSS, UI_HELV, curarea->win);
1384         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
1385         uiSetPanelHandler(IMAGE_HANDLER_PROPERTIES);  // for close and esc
1386         if(uiNewPanel(curarea, block, "Image Properties", "Image", 10, 10, 318, 204)==0)
1387                 return;
1388         
1389         /* note, it draws no bottom half in facemode, for vertex buttons */
1390         uiblock_image_panel(block, &G.sima->image, &G.sima->iuser, B_REDR, B_REDR);
1391         image_editvertex_buts(block);
1392 }       
1393
1394 static void image_panel_game_properties(short cntrl)    // IMAGE_HANDLER_GAME_PROPERTIES
1395 {
1396         ImBuf *ibuf= BKE_image_get_ibuf(G.sima->image, &G.sima->iuser);
1397         uiBlock *block;
1398
1399         block= uiNewBlock(&curarea->uiblocks, "image_panel_game_properties", UI_EMBOSS, UI_HELV, curarea->win);
1400         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
1401         uiSetPanelHandler(IMAGE_HANDLER_GAME_PROPERTIES);  // for close and esc
1402         if(uiNewPanel(curarea, block, "Real-time Properties", "Image", 10, 10, 318, 204)==0)
1403                 return;
1404
1405         if (ibuf) {
1406                 char str[128];
1407                 
1408                 image_info(G.sima->image, ibuf, str);
1409                 uiDefBut(block, LABEL, B_NOP, str,              10,180,300,19, 0, 0, 0, 0, 0, "");
1410
1411                 uiBlockBeginAlign(block);
1412                 uiDefButBitS(block, TOG, IMA_TWINANIM, B_TWINANIM, "Anim", 10,150,140,19, &G.sima->image->tpageflag, 0, 0, 0, 0, "Toggles use of animated texture");
1413                 uiDefButS(block, NUM, B_TWINANIM, "Start:",             10,130,140,19, &G.sima->image->twsta, 0.0, 128.0, 0, 0, "Displays the start frame of an animated texture");
1414                 uiDefButS(block, NUM, B_TWINANIM, "End:",               10,110,140,19, &G.sima->image->twend, 0.0, 128.0, 0, 0, "Displays the end frame of an animated texture");
1415                 uiDefButS(block, NUM, B_NOP, "Speed",                           10,90,140,19, &G.sima->image->animspeed, 1.0, 100.0, 0, 0, "Displays Speed of the animation in frames per second");
1416                 uiBlockEndAlign(block);
1417
1418                 uiBlockBeginAlign(block);
1419                 uiDefButBitS(block, TOG, IMA_TILES, B_SIMAGETILE, "Tiles",      160,150,140,19, &G.sima->image->tpageflag, 0, 0, 0, 0, "Toggles use of tilemode for faces (Shift LMB to pick the tile for selected faces)");
1420                 uiDefButS(block, NUM, B_SIMA_REDR_IMA_3D, "X:",         160,130,70,19, &G.sima->image->xrep, 1.0, 16.0, 0, 0, "Sets the degree of repetition in the X direction");
1421                 uiDefButS(block, NUM, B_SIMA_REDR_IMA_3D, "Y:",         230,130,70,19, &G.sima->image->yrep, 1.0, 16.0, 0, 0, "Sets the degree of repetition in the Y direction");
1422                 uiBlockBeginAlign(block);
1423
1424                 uiBlockBeginAlign(block);
1425                 uiDefButBitS(block, TOG, IMA_CLAMP_U, B_SIMA3DVIEWDRAW, "ClampX",       160,100,70,19, &G.sima->image->tpageflag, 0, 0, 0, 0, "Disable texture repeating horizontaly");
1426                 uiDefButBitS(block, TOG, IMA_CLAMP_V, B_SIMA3DVIEWDRAW, "ClampY",       230,100,70,19, &G.sima->image->tpageflag, 0, 0, 0, 0, "Disable texture repeating vertically");
1427                 uiBlockEndAlign(block);
1428         }
1429 }
1430
1431 static void image_panel_view_properties(short cntrl)    // IMAGE_HANDLER_VIEW_PROPERTIES
1432 {
1433         uiBlock *block;
1434
1435         block= uiNewBlock(&curarea->uiblocks, "image_view_properties", UI_EMBOSS, UI_HELV, curarea->win);
1436         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
1437         uiSetPanelHandler(IMAGE_HANDLER_VIEW_PROPERTIES);  // for close and esc
1438         if(uiNewPanel(curarea, block, "View Properties", "Image", 10, 10, 318, 204)==0)
1439                 return;
1440         
1441         
1442         uiDefButBitI(block, TOG, SI_DRAW_TILE, B_REDR, "Repeat Image",  10,160,140,19, &G.sima->flag, 0, 0, 0, 0, "Repeat/Tile the image display");
1443         uiDefButBitI(block, TOG, SI_COORDFLOATS, B_REDR, "Normalized Coords",   165,160,145,19, &G.sima->flag, 0, 0, 0, 0, "Display coords from 0.0 to 1.0 rather then in pixels");
1444         
1445         
1446         if (G.sima->image) {
1447                 uiDefBut(block, LABEL, B_NOP, "Image Display:",         10,140,140,19, 0, 0, 0, 0, 0, "");
1448                 uiBlockBeginAlign(block);
1449                 uiDefButF(block, NUM, B_REDR, "AspX:", 10,120,140,19, &G.sima->image->aspx, 0.1, 5000.0, 100, 0, "X Display Aspect for this image, does not affect renderingm 0 disables.");
1450                 uiDefButF(block, NUM, B_REDR, "AspY:", 10,100,140,19, &G.sima->image->aspy, 0.1, 5000.0, 100, 0, "X Display Aspect for this image, does not affect rendering 0 disables.");
1451                 uiBlockEndAlign(block);
1452         }
1453         
1454         
1455         if (EM_texFaceCheck()) {
1456                 uiDefBut(block, LABEL, B_NOP, "Draw Type:",             10, 80,120,19, 0, 0, 0, 0, 0, "");
1457                 uiBlockBeginAlign(block);
1458                 uiDefButC(block,  ROW, B_REDR, "Outline",               10,60,58,19, &G.sima->dt_uv, 0.0, SI_UVDT_OUTLINE, 0, 0, "Outline Wire UV drawtype");
1459                 uiDefButC(block,  ROW, B_REDR, "Dash",                  68, 60,58,19, &G.sima->dt_uv, 0.0, SI_UVDT_DASH, 0, 0, "Dashed Wire UV drawtype");
1460                 uiDefButC(block,  ROW, B_REDR, "Black",                 126, 60,58,19, &G.sima->dt_uv, 0.0, SI_UVDT_BLACK, 0, 0, "Black Wire UV drawtype");
1461                 uiDefButC(block,  ROW, B_REDR, "White",                 184,60,58,19, &G.sima->dt_uv, 0.0, SI_UVDT_WHITE, 0, 0, "White Wire UV drawtype");
1462                 
1463                 uiBlockEndAlign(block);
1464                 uiDefButBitI(block, TOG, SI_SMOOTH_UV, B_REDR, "Smooth",        250,60,60,19,  &G.sima->flag, 0, 0, 0, 0, "Display smooth lines in the UV view");
1465                 
1466                 
1467                 uiDefButBitI(block, TOG, G_DRAWFACES, B_REDR, "Faces",          10,30,60,19,  &G.f, 0, 0, 0, 0, "Displays all faces as shades in the 3d view and UV editor");
1468                 uiDefButBitI(block, TOG, G_DRAWEDGES, B_REDR, "Edges", 70, 30,60,19, &G.f, 0, 0, 0, 0, "Displays selected edges using hilights and UV editor");
1469                 
1470                 uiDefButBitI(block, TOG, SI_DRAWSHADOW, B_REDR, "Final Shadow", 130, 30,110,19, &G.sima->flag, 0, 0, 0, 0, "Draw the final result from the objects modifiers");
1471                 
1472                 uiDefButBitI(block, TOG, SI_DRAW_STRETCH, B_REDR, "UV Stretch", 10,0,100,19,  &G.sima->flag, 0, 0, 0, 0, "Difference between UV's and the 3D coords (blue for low distortion, red is high)");
1473                 if (G.sima->flag & SI_DRAW_STRETCH) {
1474                         uiBlockBeginAlign(block);
1475                         uiDefButC(block,  ROW, B_REDR, "Area",                  120,0,60,19, &G.sima->dt_uvstretch, 0.0, SI_UVDT_STRETCH_AREA, 0, 0, "Area distortion between UV's and 3D coords");
1476                         uiDefButC(block,  ROW, B_REDR, "Angle",         180,0,60,19, &G.sima->dt_uvstretch, 0.0, SI_UVDT_STRETCH_ANGLE, 0, 0, "Angle distortion between UV's and 3D coords");
1477                         uiBlockEndAlign(block);
1478                 }
1479                 
1480         }
1481         image_editcursor_buts(block);
1482 }
1483
1484 static void image_panel_paint(short cntrl)      // IMAGE_HANDLER_PAINT
1485 {
1486         /* B_SIMABRUSHCHANGE only redraws and eats the mouse messages  */
1487         /* so that LEFTMOUSE does not 'punch' through the floating panel */
1488         /* B_SIMANOTHING */
1489         ToolSettings *settings= G.scene->toolsettings;
1490         Brush *brush= settings->imapaint.brush;
1491         uiBlock *block;
1492         ID *id;
1493         int yco, xco, butw;
1494         
1495         if ((G.sima->image && (G.sima->flag & SI_DRAWTOOL))==0) {
1496                 return;
1497         }
1498         
1499         block= uiNewBlock(&curarea->uiblocks, "image_panel_paint", UI_EMBOSS, UI_HELV, curarea->win);
1500         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
1501         uiSetPanelHandler(IMAGE_HANDLER_PAINT);  // for close and esc
1502         if(uiNewPanel(curarea, block, "Image Paint", "Image", 10, 230, 318, 204)==0)
1503                 return;
1504
1505         yco= 160;
1506
1507         uiBlockBeginAlign(block);
1508         uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Draw",                0  ,yco,80,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_DRAW, 0, 0, "Draw brush");
1509         uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Soften",              80 ,yco,80,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SOFTEN, 0, 0, "Soften brush");
1510         uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Smear",               160,yco,80,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SMEAR, 0, 0, "Smear brush");   
1511         uiDefButS(block, ROW, B_SIMABRUSHCHANGE, "Clone",               240,yco,80,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_CLONE, 0, 0, "Clone brush, use RMB to drag source image");     
1512         uiBlockEndAlign(block);
1513         yco -= 30;
1514
1515         uiBlockSetCol(block, TH_BUT_SETTING2);
1516         id= (ID*)settings->imapaint.brush;
1517         xco= std_libbuttons(block, 0, yco, 0, NULL, B_SIMABRUSHBROWSE, ID_BR, 0, id, NULL, &(G.sima->menunr), 0, B_SIMABRUSHLOCAL, B_SIMABRUSHDELETE, 0, B_KEEPDATA);
1518         uiBlockSetCol(block, TH_AUTO);
1519
1520         if(brush && !brush->id.lib) {
1521                 butw= 320-(xco+10);
1522
1523                 uiDefButS(block, MENU, B_SIMANOTHING, "Mix %x0|Add %x1|Subtract %x2|Multiply %x3|Lighten %x4|Darken %x5|Erase Alpha %x6|Add Alpha %x7", xco+10,yco,butw,19, &brush->blend, 0, 0, 0, 0, "Blending method for applying brushes");
1524
1525                 uiDefButBitS(block, TOG|BIT, BRUSH_TORUS, B_SIMABRUSHCHANGE, "Wrap",    xco+10,yco-25,butw,19, &brush->flag, 0, 0, 0, 0, "Enables torus wrapping");
1526
1527                 uiBlockBeginAlign(block);
1528                 uiDefButBitS(block, TOG|BIT, BRUSH_AIRBRUSH, B_SIMABRUSHCHANGE, "Airbrush",     xco+10,yco-50,butw,19, &brush->flag, 0, 0, 0, 0, "Keep applying paint effect while holding mouse (spray)");
1529                 uiDefButF(block, NUM, B_SIMANOTHING, "Rate ", xco+10,yco-70,butw,19, &brush->rate, 0.01, 1.0, 0, 0, "Number of paints per second for Airbrush");
1530                 uiBlockEndAlign(block);
1531
1532                 yco -= 25;
1533
1534                 uiBlockBeginAlign(block);
1535                 uiDefButF(block, COL, B_VPCOLSLI, "",                                   0,yco,200,19, brush->rgb, 0, 0, 0, 0, "");
1536                 uiDefButF(block, NUMSLI, B_SIMANOTHING, "Opacity ",             0,yco-20,180,19, &brush->alpha, 0.0, 1.0, 0, 0, "The amount of pressure on the brush");
1537                 uiDefButBitS(block, TOG|BIT, BRUSH_ALPHA_PRESSURE, B_SIMANOTHING, "P",  180,yco-20,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets");
1538                 uiDefButI(block, NUMSLI, B_SIMANOTHING, "Size ",                0,yco-40,180,19, &brush->size, 1, 200, 0, 0, "The size of the brush");
1539                 uiDefButBitS(block, TOG|BIT, BRUSH_SIZE_PRESSURE, B_SIMANOTHING, "P",   180,yco-40,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets");
1540                 uiDefButF(block, NUMSLI, B_SIMANOTHING, "Falloff ",             0,yco-60,180,19, &brush->innerradius, 0.0, 1.0, 0, 0, "The fall off radius of the brush");
1541                 uiDefButBitS(block, TOG|BIT, BRUSH_RAD_PRESSURE, B_SIMANOTHING, "P",    180,yco-60,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets");
1542                 uiDefButF(block, NUMSLI, B_SIMANOTHING, "Spacing ",0,yco-80,180,19, &brush->spacing, 1.0, 100.0, 0, 0, "Repeating paint on %% of brush diameter");
1543                 uiDefButBitS(block, TOG|BIT, BRUSH_SPACING_PRESSURE, B_SIMANOTHING, "P",        180,yco-80,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets");
1544                 uiBlockEndAlign(block);
1545
1546                 yco -= 110;
1547
1548                 if(settings->imapaint.tool == PAINT_TOOL_CLONE) {
1549                         id= (ID*)brush->clone.image;
1550                         uiBlockSetCol(block, TH_BUT_SETTING2);
1551                         xco= std_libbuttons(block, 0, yco, 0, NULL, B_SIMACLONEBROWSE, ID_IM, 0, id, 0, &G.sima->menunr, 0, 0, B_SIMACLONEDELETE, 0, 0);
1552                         uiBlockSetCol(block, TH_AUTO);
1553                         if(id) {
1554                                 butw= 320-(xco+5);
1555                                 uiDefButF(block, NUMSLI, B_SIMABRUSHCHANGE, "B ",xco+5,yco,butw,19, &brush->clone.alpha , 0.0, 1.0, 0, 0, "Opacity of clone image display");
1556                         }
1557                 }
1558                 else {
1559                         MTex *mtex= brush->mtex[brush->texact];
1560
1561                         uiBlockSetCol(block, TH_BUT_SETTING2);
1562                         id= (mtex)? (ID*)mtex->tex: NULL;
1563                         xco= std_libbuttons(block, 0, yco, 0, NULL, B_SIMABTEXBROWSE, ID_TE, 0, id, NULL, &(G.sima->menunr), 0, 0, B_SIMABTEXDELETE, 0, 0);
1564                         /*uiDefButBitS(block, TOG|BIT, BRUSH_FIXED_TEX, B_SIMABRUSHCHANGE, "Fixed",     xco+5,yco,butw,19, &brush->flag, 0, 0, 0, 0, "Keep texture origin in fixed position");*/
1565                         uiBlockSetCol(block, TH_AUTO);
1566                 }
1567         }
1568
1569 #if 0
1570                 uiDefButBitS(block, TOG|BIT, IMAGEPAINT_DRAW_TOOL_DRAWING, B_SIMABRUSHCHANGE, "TD", 0,1,50,19, &settings->imapaint.flag.flag, 0, 0, 0, 0, "Enables brush shape while drawing");
1571                 uiDefButBitS(block, TOG|BIT, IMAGEPAINT_DRAW_TOOL, B_SIMABRUSHCHANGE, "TP", 50,1,50,19, &settings->imapaint.flag.flag, 0, 0, 0, 0, "Enables brush shape while not drawing");
1572 #endif
1573 }
1574
1575 static void image_panel_curves_reset(void *cumap_v, void *ibuf_v)
1576 {
1577         CurveMapping *cumap = cumap_v;
1578         int a;
1579         
1580         for(a=0; a<CM_TOT; a++)
1581                 curvemap_reset(cumap->cm+a, &cumap->clipr);
1582         
1583         cumap->black[0]=cumap->black[1]=cumap->black[2]= 0.0f;
1584         cumap->white[0]=cumap->white[1]=cumap->white[2]= 1.0f;
1585         curvemapping_set_black_white(cumap, NULL, NULL);
1586         
1587         curvemapping_changed(cumap, 0);
1588         curvemapping_do_ibuf(cumap, ibuf_v);
1589         
1590         allqueue(REDRAWIMAGE, 0);
1591 }
1592
1593
1594 static void image_panel_curves(short cntrl)     // IMAGE_HANDLER_CURVES
1595 {
1596         ImBuf *ibuf;
1597         uiBlock *block;
1598         uiBut *bt;
1599         
1600         /* and we check for spare */
1601         ibuf= imagewindow_get_ibuf(G.sima);
1602         
1603         block= uiNewBlock(&curarea->uiblocks, "image_panel_curves", UI_EMBOSS, UI_HELV, curarea->win);
1604         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
1605         uiSetPanelHandler(IMAGE_HANDLER_CURVES);  // for close and esc
1606         if(uiNewPanel(curarea, block, "Curves", "Image", 10, 450, 318, 204)==0)
1607                 return;
1608         
1609         if (ibuf) {
1610                 rctf rect;
1611                 
1612                 if(G.sima->cumap==NULL)
1613                         G.sima->cumap= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
1614                 
1615                 rect.xmin= 110; rect.xmax= 310;
1616                 rect.ymin= 10; rect.ymax= 200;
1617                 curvemap_buttons(block, G.sima->cumap, 'c', B_SIMACURVES, B_REDR, &rect);
1618                 
1619                 bt=uiDefBut(block, BUT, B_SIMARANGE, "Reset",   10, 160, 90, 19, NULL, 0.0f, 0.0f, 0, 0, "Reset Black/White point and curves");
1620                 uiButSetFunc(bt, image_panel_curves_reset, G.sima->cumap, ibuf);
1621                 
1622                 uiBlockBeginAlign(block);
1623                 uiDefButF(block, NUM, B_SIMARANGE, "Min R:",    10, 120, 90, 19, G.sima->cumap->black, -1000.0f, 1000.0f, 10, 2, "Black level");
1624                 uiDefButF(block, NUM, B_SIMARANGE, "Min G:",    10, 100, 90, 19, G.sima->cumap->black+1, -1000.0f, 1000.0f, 10, 2, "Black level");
1625                 uiDefButF(block, NUM, B_SIMARANGE, "Min B:",    10, 80, 90, 19, G.sima->cumap->black+2, -1000.0f, 1000.0f, 10, 2, "Black level");
1626                 
1627                 uiBlockBeginAlign(block);
1628                 uiDefButF(block, NUM, B_SIMARANGE, "Max R:",    10, 50, 90, 19, G.sima->cumap->white, -1000.0f, 1000.0f, 10, 2, "White level");
1629                 uiDefButF(block, NUM, B_SIMARANGE, "Max G:",    10, 30, 90, 19, G.sima->cumap->white+1, -1000.0f, 1000.0f, 10, 2, "White level");
1630                 uiDefButF(block, NUM, B_SIMARANGE, "Max B:",    10, 10, 90, 19, G.sima->cumap->white+2, -1000.0f, 1000.0f, 10, 2, "White level");
1631                 
1632         }
1633 }
1634
1635 /* are there curves? curves visible? and curves do something? */
1636 static int image_curves_active(ScrArea *sa)
1637 {
1638         SpaceImage *sima= sa->spacedata.first;
1639
1640         if(sima->cumap) {
1641                 if(curvemapping_RGBA_does_something(sima->cumap)) {
1642                         short a;
1643                         for(a=0; a<SPACE_MAXHANDLER; a+=2) {
1644                                 if(sima->blockhandler[a] == IMAGE_HANDLER_CURVES)
1645                                         return 1;
1646                         }
1647                 }
1648         }
1649         return 0;
1650 }
1651
1652 /* 0: disable preview 
1653    otherwise refresh preview
1654 */
1655 void image_preview_event(int event)
1656 {
1657         int exec= 0;
1658         
1659
1660         if(event==0) {
1661                 G.scene->r.scemode &= ~R_COMP_CROP;
1662                 exec= 1;
1663         }
1664         else {
1665                 if(image_preview_active(curarea, NULL, NULL)) {
1666                         G.scene->r.scemode |= R_COMP_CROP;
1667                         exec= 1;
1668                 }
1669                 else
1670                         G.scene->r.scemode &= ~R_COMP_CROP;
1671         }
1672         
1673         if(exec && G.scene->nodetree) {
1674                 /* should work when no node editor in screen..., so we execute right away */
1675                 
1676                 ntreeCompositTagGenerators(G.scene->nodetree);
1677
1678                 G.afbreek= 0;
1679                 G.scene->nodetree->timecursor= set_timecursor;
1680                 G.scene->nodetree->test_break= blender_test_break;
1681                 
1682                 BIF_store_spare();
1683                 
1684                 ntreeCompositExecTree(G.scene->nodetree, &G.scene->r, 1);       /* 1 is do_previews */
1685                 
1686                 G.scene->nodetree->timecursor= NULL;
1687                 G.scene->nodetree->test_break= NULL;
1688                 
1689                 scrarea_do_windraw(curarea);
1690                 waitcursor(0);
1691                 
1692                 allqueue(REDRAWNODE, 1);
1693         }       
1694 }
1695
1696
1697 /* nothing drawn here, we use it to store values */
1698 static void preview_cb(struct ScrArea *sa, struct uiBlock *block)
1699 {
1700         rctf dispf;
1701         rcti *disprect= &G.scene->r.disprect;
1702         int winx= (G.scene->r.size*G.scene->r.xsch)/100;
1703         int winy= (G.scene->r.size*G.scene->r.ysch)/100;
1704         short mval[2];
1705         
1706         if(G.scene->r.mode & R_BORDER) {
1707                 winx*= (G.scene->r.border.xmax - G.scene->r.border.xmin);
1708                 winy*= (G.scene->r.border.ymax - G.scene->r.border.ymin);
1709         }
1710         
1711         /* while dragging we need to update the rects, otherwise it doesn't end with correct one */
1712
1713         BLI_init_rctf(&dispf, 15.0f, (block->maxx - block->minx)-15.0f, 15.0f, (block->maxy - block->miny)-15.0f);
1714         ui_graphics_to_window_rct(sa->win, &dispf, disprect);
1715         
1716         /* correction for gla draw */
1717         BLI_translate_rcti(disprect, -curarea->winrct.xmin, -curarea->winrct.ymin);
1718         
1719         calc_image_view(G.sima, 'p');
1720 //      printf("winrct %d %d %d %d\n", disprect->xmin, disprect->ymin,disprect->xmax, disprect->ymax);
1721         /* map to image space coordinates */
1722         mval[0]= disprect->xmin; mval[1]= disprect->ymin;
1723         areamouseco_to_ipoco(G.v2d, mval, &dispf.xmin, &dispf.ymin);
1724         mval[0]= disprect->xmax; mval[1]= disprect->ymax;
1725         areamouseco_to_ipoco(G.v2d, mval, &dispf.xmax, &dispf.ymax);
1726         
1727         /* map to render coordinates */
1728         disprect->xmin= dispf.xmin;
1729         disprect->xmax= dispf.xmax;
1730         disprect->ymin= dispf.ymin;
1731         disprect->ymax= dispf.ymax;
1732         
1733         CLAMP(disprect->xmin, 0, winx);
1734         CLAMP(disprect->xmax, 0, winx);
1735         CLAMP(disprect->ymin, 0, winy);
1736         CLAMP(disprect->ymax, 0, winy);
1737 //      printf("drawrct %d %d %d %d\n", disprect->xmin, disprect->ymin,disprect->xmax, disprect->ymax);
1738
1739 }
1740
1741 static int is_preview_allowed(ScrArea *cur)
1742 {
1743         SpaceImage *sima= cur->spacedata.first;
1744         ScrArea *sa;
1745
1746         /* check if another areawindow has preview set */
1747         for(sa=G.curscreen->areabase.first; sa; sa= sa->next) {
1748                 if(sa!=cur && sa->spacetype==SPACE_IMAGE) {
1749                         if(image_preview_active(sa, NULL, NULL))
1750                            return 0;
1751                 }
1752         }
1753         /* check image type */
1754         if(sima->image==NULL || sima->image->type!=IMA_TYPE_COMPOSITE)
1755                 return 0;
1756         
1757         return 1;
1758 }
1759
1760 static void image_panel_preview(ScrArea *sa, short cntrl)       // IMAGE_HANDLER_PREVIEW
1761 {
1762         uiBlock *block;
1763         SpaceImage *sima= sa->spacedata.first;
1764         int ofsx, ofsy;
1765         
1766         if(is_preview_allowed(sa)==0) {
1767                 rem_blockhandler(sa, IMAGE_HANDLER_PREVIEW);
1768                 G.scene->r.scemode &= ~R_COMP_CROP;     /* quite weak */
1769                 return;
1770         }
1771         
1772         block= uiNewBlock(&sa->uiblocks, "image_panel_preview", UI_EMBOSS, UI_HELV, sa->win);
1773         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | UI_PNL_SCALE | cntrl);
1774         uiSetPanelHandler(IMAGE_HANDLER_PREVIEW);  // for close and esc
1775         
1776         ofsx= -150+(sa->winx/2)/sima->blockscale;
1777         ofsy= -100+(sa->winy/2)/sima->blockscale;
1778         if(uiNewPanel(sa, block, "Preview", "Image", ofsx, ofsy, 300, 200)==0) return;
1779         
1780         uiBlockSetDrawExtraFunc(block, preview_cb);
1781         
1782 }
1783
1784 static void image_panel_gpencil(short cntrl)    // IMAGE_HANDLER_GREASEPENCIL
1785 {
1786         uiBlock *block;
1787         SpaceImage *sima;
1788         
1789         sima= curarea->spacedata.first;
1790
1791         block= uiNewBlock(&curarea->uiblocks, "image_panel_gpencil", UI_EMBOSS, UI_HELV, curarea->win);
1792         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE  | cntrl);
1793         uiSetPanelHandler(IMAGE_HANDLER_GREASEPENCIL);  // for close and esc
1794         if (uiNewPanel(curarea, block, "Grease Pencil", "SpaceImage", 100, 30, 318, 204)==0) return;
1795         
1796         /* allocate memory for gpd if drawing enabled (this must be done first or else we crash) */
1797         if (sima->flag & SI_DISPGP) {
1798                 if (sima->gpd == NULL)
1799                         gpencil_data_setactive(curarea, gpencil_data_addnew());
1800         }
1801         
1802         if (sima->flag & SI_DISPGP) {
1803                 bGPdata *gpd= sima->gpd;
1804                 short newheight;
1805                 
1806                 /* this is a variable height panel, newpanel doesnt force new size on existing panels */
1807                 /* so first we make it default height */
1808                 uiNewPanelHeight(block, 204);
1809                 
1810                 /* draw button for showing gpencil settings and drawings */
1811                 uiDefButBitI(block, TOG, SI_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &sima->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Image/UV Editor (draw using Shift-LMB)");
1812                 
1813                 /* extend the panel if the contents won't fit */
1814                 newheight= draw_gpencil_panel(block, gpd, curarea); 
1815                 uiNewPanelHeight(block, newheight);
1816         }
1817         else {
1818                 uiDefButBitI(block, TOG, SI_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &sima->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Image/UV Editor");
1819                 uiDefBut(block, LABEL, 1, " ",  160, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
1820         }
1821 }
1822
1823 static void image_blockhandlers(ScrArea *sa)
1824 {
1825         SpaceImage *sima= sa->spacedata.first;
1826         short a;
1827
1828         /* warning; blocks need to be freed each time, handlers dont remove  */
1829         uiFreeBlocksWin(&sa->uiblocks, sa->win);
1830         
1831         for(a=0; a<SPACE_MAXHANDLER; a+=2) {
1832                 switch(sima->blockhandler[a]) {
1833                 case IMAGE_HANDLER_PROPERTIES:
1834                         image_panel_properties(sima->blockhandler[a+1]);
1835                         break;
1836                 case IMAGE_HANDLER_GAME_PROPERTIES:
1837                         image_panel_game_properties(sima->blockhandler[a+1]);
1838                         break;
1839                 case IMAGE_HANDLER_VIEW_PROPERTIES:
1840                         image_panel_view_properties(sima->blockhandler[a+1]);
1841                         break;
1842                 case IMAGE_HANDLER_PAINT:
1843                         image_panel_paint(sima->blockhandler[a+1]);
1844                         break;          
1845                 case IMAGE_HANDLER_CURVES:
1846                         image_panel_curves(sima->blockhandler[a+1]);
1847                         break;          
1848                 case IMAGE_HANDLER_PREVIEW:
1849                         image_panel_preview(sa, sima->blockhandler[a+1]);
1850                         break;  
1851                 case IMAGE_HANDLER_GREASEPENCIL:
1852                         image_panel_gpencil(sima->blockhandler[a+1]);
1853                         break;
1854                 }
1855                 /* clear action value for event */
1856                 sima->blockhandler[a+1]= 0;
1857         }
1858         uiDrawBlocksPanels(sa, 0);
1859 }
1860
1861 void imagespace_composite_flipbook(ScrArea *sa)
1862 {
1863         SpaceImage *sima= sa->spacedata.first;
1864         ImBuf *ibuf;
1865         int cfrao= G.scene->r.cfra;
1866         int sfra, efra;
1867         
1868         if(sa->spacetype!=SPACE_IMAGE)
1869                 return;
1870         if(sima->iuser.frames<2)
1871                 return;
1872         if(G.scene->nodetree==NULL)
1873                 return;
1874         
1875         sfra= sima->iuser.sfra;
1876         efra= sima->iuser.sfra + sima->iuser.frames-1;
1877         G.scene->nodetree->test_break= blender_test_break;
1878         
1879         for(G.scene->r.cfra=sfra; G.scene->r.cfra<=efra; G.scene->r.cfra++) {
1880                 
1881                 set_timecursor(CFRA);
1882                 
1883                 BKE_image_all_free_anim_ibufs(CFRA);
1884                 ntreeCompositTagAnimated(G.scene->nodetree);
1885                 ntreeCompositExecTree(G.scene->nodetree, &G.scene->r, G.scene->r.cfra!=cfrao);  /* 1 is no previews */
1886                 
1887                 force_draw(0);
1888                 
1889                 ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser);
1890                 /* save memory in flipbooks */
1891                 if(ibuf)
1892                         imb_freerectfloatImBuf(ibuf);
1893                 
1894                 if(blender_test_break())
1895                         break;
1896         }
1897         G.scene->nodetree->test_break= NULL;
1898         waitcursor(0);
1899         
1900         play_anim(0);
1901         
1902         allqueue(REDRAWNODE, 1);
1903         allqueue(REDRAWIMAGE, 1);
1904         
1905         G.scene->r.cfra= cfrao;
1906 }
1907
1908 static void imagespace_grid(SpaceImage *sima)
1909 {
1910         float gridsize, gridstep= 1.0f/32.0f;
1911         float fac, blendfac;
1912         
1913         gridsize= sima->zoom;
1914         
1915         calc_image_view(sima, 'f');
1916         myortho2(sima->v2d.cur.xmin, sima->v2d.cur.xmax, sima->v2d.cur.ymin, sima->v2d.cur.ymax);
1917         
1918         BIF_ThemeColorShade(TH_BACK, 20);
1919         glRectf(0.0, 0.0, 1.0, 1.0);
1920         
1921         if(gridsize<=0.0f) return;
1922         
1923         if(gridsize<1.0f) {
1924                 while(gridsize<1.0f) {
1925                         gridsize*= 4.0;
1926                         gridstep*= 4.0;
1927                 }
1928         }
1929         else {
1930                 while(gridsize>=4.0f) {
1931                         gridsize/= 4.0;
1932                         gridstep/= 4.0;
1933                 }
1934         }
1935         
1936         /* the fine resolution level */
1937         blendfac= 0.25*gridsize - floor(0.25*gridsize);
1938         CLAMP(blendfac, 0.0, 1.0);
1939         BIF_ThemeColorShade(TH_BACK, (int)(20.0*(1.0-blendfac)));
1940         
1941         fac= 0.0f;
1942         glBegin(GL_LINES);
1943         while(fac<1.0) {
1944                 glVertex2f(0.0f, fac);
1945                 glVertex2f(1.0f, fac);
1946                 glVertex2f(fac, 0.0f);
1947                 glVertex2f(fac, 1.0f);
1948                 fac+= gridstep;
1949         }
1950         
1951         /* the large resolution level */
1952         BIF_ThemeColor(TH_BACK);
1953         
1954         fac= 0.0f;
1955         while(fac<1.0) {
1956                 glVertex2f(0.0f, fac);
1957                 glVertex2f(1.0f, fac);
1958                 glVertex2f(fac, 0.0f);
1959                 glVertex2f(fac, 1.0f);
1960                 fac+= 4.0*gridstep;
1961         }
1962         glEnd();
1963         
1964 }
1965
1966 static void sima_draw_alpha_backdrop(SpaceImage *sima, float x1, float y1, float xsize, float ysize)
1967 {
1968         GLubyte checker_stipple[32*32/8] =
1969         {
1970                 255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0, \
1971                 255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0, \
1972                 255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0, \
1973                 255,255,0,0,255,255,0,0,255,255,0,0,255,255,0,0, \
1974                 0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255, \
1975                 0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255, \
1976                 0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255, \
1977                 0,0,255,255,0,0,255,255,0,0,255,255,0,0,255,255, \
1978         };
1979         
1980         glColor3ub(100, 100, 100);
1981         glRectf(x1, y1, x1 + sima->zoom*xsize, y1 + sima->zoom*ysize);
1982         glColor3ub(160, 160, 160);
1983
1984         glEnable(GL_POLYGON_STIPPLE);
1985         glPolygonStipple(checker_stipple);
1986         glRectf(x1, y1, x1 + sima->zoom*xsize, y1 + sima->zoom*ysize);
1987         glDisable(GL_POLYGON_STIPPLE);
1988 }
1989
1990 static void sima_draw_alpha_pixels(float x1, float y1, int rectx, int recty, unsigned int *recti)
1991 {
1992         
1993         /* swap bytes, so alpha is most significant one, then just draw it as luminance int */
1994         if(G.order==B_ENDIAN)
1995                 glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
1996         glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_UNSIGNED_INT, recti);
1997         glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
1998 }
1999
2000 static void sima_draw_alpha_pixelsf(float x1, float y1, int rectx, int recty, float *rectf)
2001 {
2002         float *trectf= MEM_mallocN(rectx*recty*4, "temp");
2003         int a, b;
2004         
2005         for(a= rectx*recty -1, b= 4*a+3; a>=0; a--, b-=4)
2006                 trectf[a]= rectf[b];
2007         
2008         glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_FLOAT, trectf);
2009         MEM_freeN(trectf);
2010         /* ogl trick below is slower... (on ATI 9600) */
2011 //      glColorMask(1, 0, 0, 0);
2012 //      glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf+3);
2013 //      glColorMask(0, 1, 0, 0);
2014 //      glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf+2);
2015 //      glColorMask(0, 0, 1, 0);
2016 //      glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf+1);
2017 //      glColorMask(1, 1, 1, 1);
2018 }
2019
2020 static void sima_draw_zbuf_pixels(float x1, float y1, int rectx, int recty, int *recti)
2021 {
2022         if(recti==NULL)
2023                 return;
2024         
2025         /* zbuffer values are signed, so we need to shift color range */
2026         glPixelTransferf(GL_RED_SCALE, 0.5f);
2027         glPixelTransferf(GL_GREEN_SCALE, 0.5f);
2028         glPixelTransferf(GL_BLUE_SCALE, 0.5f);
2029         glPixelTransferf(GL_RED_BIAS, 0.5f);
2030         glPixelTransferf(GL_GREEN_BIAS, 0.5f);
2031         glPixelTransferf(GL_BLUE_BIAS, 0.5f);
2032         
2033         glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_INT, recti);
2034         
2035         glPixelTransferf(GL_RED_SCALE, 1.0f);
2036         glPixelTransferf(GL_GREEN_SCALE, 1.0f);
2037         glPixelTransferf(GL_BLUE_SCALE, 1.0f);
2038         glPixelTransferf(GL_RED_BIAS, 0.0f);
2039         glPixelTransferf(GL_GREEN_BIAS, 0.0f);
2040         glPixelTransferf(GL_BLUE_BIAS, 0.0f);
2041 }
2042
2043 static void sima_draw_zbuffloat_pixels(float x1, float y1, int rectx, int recty, float *rect_float)
2044 {
2045         float bias, scale, *rectf, clipend;
2046         int a;
2047         
2048         if(rect_float==NULL)
2049                 return;
2050         
2051         if(G.scene->camera && G.scene->camera->type==OB_CAMERA) {
2052                 bias= ((Camera *)G.scene->camera->data)->clipsta;
2053                 clipend= ((Camera *)G.scene->camera->data)->clipend;
2054                 scale= 1.0f/(clipend-bias);
2055         }
2056         else {
2057                 bias= 0.1f;
2058                 scale= 0.01f;
2059                 clipend= 100.0f;
2060         }
2061         
2062         rectf= MEM_mallocN(rectx*recty*4, "temp");
2063         for(a= rectx*recty -1; a>=0; a--) {
2064                 if(rect_float[a]>clipend)
2065                         rectf[a]= 0.0f;
2066                 else if(rect_float[a]<bias)
2067                         rectf[a]= 1.0f;
2068                 else {
2069                         rectf[a]= 1.0f - (rect_float[a]-bias)*scale;
2070                         rectf[a]*= rectf[a];
2071                 }
2072         }
2073         glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_FLOAT, rectf);
2074         
2075         MEM_freeN(rectf);
2076 }
2077
2078 static void imagewindow_draw_renderinfo(ScrArea *sa)
2079 {
2080         rcti rect;
2081         float colf[3];
2082         int showspare= BIF_show_render_spare();
2083         char *str= BIF_render_text();
2084         
2085         if(str==NULL)
2086                 return;
2087         
2088         rect= sa->winrct;
2089         rect.ymin= rect.ymax-RW_HEADERY;
2090         
2091         glaDefine2DArea(&rect);
2092         
2093         /* clear header rect */
2094         BIF_GetThemeColor3fv(TH_BACK, colf);
2095         glClearColor(colf[0]+0.1f, colf[1]+0.1f, colf[2]+0.1f, 1.0); 
2096         glClear(GL_COLOR_BUFFER_BIT);
2097         
2098         BIF_ThemeColor(TH_TEXT_HI);
2099         glRasterPos2i(12, 5);
2100         if(showspare) {
2101                 BMF_DrawString(G.fonts, "(Previous)");
2102                 glRasterPos2i(72, 5);
2103         }               
2104         BMF_DrawString(G.fonts, str);
2105 }
2106
2107 void drawimagespace(ScrArea *sa, void *spacedata)
2108 {
2109         SpaceImage *sima= spacedata;
2110         ImBuf *ibuf= NULL;
2111         Brush *brush;
2112         float col[3];
2113         unsigned int *rect;
2114         float x1, y1;
2115         short sx, sy, dx, dy, show_render= 0, show_viewer= 0;
2116         float xuser_asp=1, yuser_asp=1;
2117                 /* If derived data is used then make sure that object
2118                  * is up-to-date... might not be the case because updates
2119                  * are normally done in drawview and could get here before
2120                  * drawing a View3D.
2121                  */
2122         if (G.obedit && OBACT && (sima->flag & SI_DRAWSHADOW)) {
2123                 object_handle_update(OBACT);
2124         }
2125         
2126         BIF_GetThemeColor3fv(TH_BACK, col);
2127         glClearColor(col[0], col[1], col[2], 0.0);
2128         glClear(GL_COLOR_BUFFER_BIT);
2129
2130         bwin_clear_viewmat(sa->win);    /* clear buttons view */
2131         glLoadIdentity();
2132         
2133         if(sima->image && sima->image->source==IMA_SRC_VIEWER) {
2134                 show_viewer= 1;
2135                 if(sima->image->type==IMA_TYPE_R_RESULT)
2136                         show_render= 1;
2137         }
2138         
2139         what_image(sima);
2140         
2141         if(sima->image) {
2142                 image_pixel_aspect(sima->image, &xuser_asp, &yuser_asp);
2143                 
2144                 /* UGLY hack? until now iusers worked fine... but for flipbook viewer we need this */
2145                 if(sima->image->type==IMA_TYPE_COMPOSITE) {
2146                         ImageUser *iuser= ntree_get_active_iuser(G.scene->nodetree);
2147                         if(iuser) {
2148                                 BKE_image_user_calc_imanr(iuser, G.scene->r.cfra, 0);
2149                                 G.sima->iuser= *iuser;
2150                         }
2151                 }
2152                 /* and we check for spare */
2153                 ibuf= imagewindow_get_ibuf(sima);
2154         }
2155         
2156         if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
2157                 imagespace_grid(sima);
2158                 if(show_viewer==0) {
2159                         draw_uvs_sima();
2160                         drawcursor_sima(xuser_asp, yuser_asp);
2161                 }
2162         }
2163         else {
2164                 float xim, yim, xoffs=0.0f, yoffs= 0.0f;
2165                 
2166                 if(image_preview_active(sa, &xim, &yim)) {
2167                         xoffs= G.scene->r.disprect.xmin;
2168                         yoffs= G.scene->r.disprect.ymin;
2169                         glColor3ub(0,0,0);
2170                         calc_image_view(sima, 'f');     
2171                         myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
2172                         glRectf(0.0f, 0.0f, 1.0f, 1.0f);
2173                         glLoadIdentity();
2174                 }
2175                 else {
2176                         xim= ibuf->x * xuser_asp; yim= ibuf->y * yuser_asp;
2177                 }
2178                 
2179                 /* calc location */
2180                 x1= sima->zoom*xoffs + ((float)sa->winx - sima->zoom*(float)xim)/2.0f;
2181                 y1= sima->zoom*yoffs + ((float)sa->winy - sima->zoom*(float)yim)/2.0f;
2182         
2183                 x1-= sima->zoom*sima->xof;
2184                 y1-= sima->zoom*sima->yof;
2185                 
2186                 /* needed for gla draw */
2187                 if(show_render) { 
2188                         rcti rct= sa->winrct; 
2189                         
2190                         imagewindow_draw_renderinfo(sa);        /* calls glaDefine2DArea too */
2191                         
2192                         rct.ymax-=RW_HEADERY; 
2193                         glaDefine2DArea(&rct);
2194                 }
2195                 else glaDefine2DArea(&sa->winrct);
2196                 
2197                 glPixelZoom(sima->zoom * xuser_asp, sima->zoom * yuser_asp);
2198                                 
2199                 if(sima->flag & SI_EDITTILE) {
2200                         /* create char buffer from float if needed */
2201                         if(ibuf->rect_float && ibuf->rect==NULL)
2202                                 IMB_rect_from_float(ibuf);
2203
2204                         glaDrawPixelsSafe(x1, y1, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
2205                         
2206                         glPixelZoom(1.0, 1.0);
2207                         
2208                         dx= ibuf->x/sima->image->xrep;
2209                         dy= ibuf->y/sima->image->yrep;
2210                         sy= (sima->curtile / sima->image->xrep);
2211                         sx= sima->curtile - sy*sima->image->xrep;
2212         
2213                         sx*= dx;
2214                         sy*= dy;
2215                         
2216                         calc_image_view(sima, 'p');     /* pixel */
2217                         myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
2218                         
2219                         cpack(0x0);
2220                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glRects(sx,  sy,  sx+dx-1,  sy+dy-1); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2221                         cpack(0xFFFFFF);
2222                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glRects(sx+1,  sy+1,  sx+dx,  sy+dy); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2223                 }
2224                 else if(sima->mode==SI_TEXTURE) {
2225                         
2226                         if(sima->image->tpageflag & IMA_TILES) {
2227                                 
2228                                 /* just leave this a while */
2229                                 if(sima->image->xrep<1) return;
2230                                 if(sima->image->yrep<1) return;
2231                                 
2232                                 if(sima->curtile >= sima->image->xrep*sima->image->yrep) 
2233                                         sima->curtile = sima->image->xrep*sima->image->yrep - 1; 
2234                                 
2235                                 dx= ibuf->x/sima->image->xrep;
2236                                 dy= ibuf->y/sima->image->yrep;
2237                                 
2238                                 sy= (sima->curtile / sima->image->xrep);
2239                                 sx= sima->curtile - sy*sima->image->xrep;
2240                 
2241                                 sx*= dx;
2242                                 sy*= dy;
2243                                 
2244                                 /* create char buffer from float if needed */
2245                                 if(ibuf->rect_float && ibuf->rect==NULL)
2246                                         IMB_rect_from_float(ibuf);
2247
2248                                 rect= get_part_from_ibuf(ibuf, sx, sy, sx+dx, sy+dy);
2249                                 
2250                                 /* rect= ibuf->rect; */
2251                                 for(sy= 0; sy+dy<=ibuf->y; sy+= dy) {
2252                                         for(sx= 0; sx+dx<=ibuf->x; sx+= dx) {
2253                                                 glaDrawPixelsSafe(x1+sx*sima->zoom, y1+sy*sima->zoom, dx, dy, dx, GL_RGBA, GL_UNSIGNED_BYTE, rect);
2254                                         }
2255                                 }
2256                                 
2257                                 MEM_freeN(rect);
2258                         }
2259                         else {
2260                                 float x1_rep, y1_rep;
2261                                 int x_rep, y_rep;
2262                                 double time_current;
2263                                 short loop_draw_ok = 0;
2264                                 
2265                                 if (sima->flag & SI_DRAW_TILE) {
2266                                         loop_draw_ok= 1;
2267                                 }
2268                                 
2269                                 time_current = PIL_check_seconds_timer();
2270                                 
2271                                 for (x_rep= ((int)G.v2d->cur.xmin)-1; x_rep < G.v2d->cur.xmax; x_rep++) {
2272                                         x1_rep=x1+  ((x_rep* ibuf->x * sima->zoom)  *xuser_asp);
2273                                         for (y_rep= ((int)G.v2d->cur.ymin)-1; y_rep < G.v2d->cur.ymax; y_rep++) {
2274                                                 y1_rep=y1+  ((y_rep * ibuf->y *sima->zoom)  *yuser_asp);
2275                                 
2276                                 /* end repeating image loop */
2277                                                 
2278                                                 if(!loop_draw_ok) {
2279                                                         y1_rep = y1;
2280                                                         x1_rep = x1;
2281                                                 }
2282                                                 
2283                                                 /*printf("Drawing %d %d zoom:%.6f (%.6f %.6f), (%.6f %.6f)\n", x_rep, y_rep, sima->zoom, G.v2d->cur.xmin, G.v2d->cur.ymin, G.v2d->cur.xmax, G.v2d->cur.ymax);*/
2284                                                 
2285                                                 /* this part is generic image display */
2286                                                 if(sima->flag & SI_SHOW_ALPHA) {
2287                                                         if(ibuf->rect)
2288                                                                 sima_draw_alpha_pixels(x1_rep, y1_rep, ibuf->x, ibuf->y, ibuf->rect);
2289                                                         else if(ibuf->rect_float && ibuf->channels==4)
2290                                                                 sima_draw_alpha_pixelsf(x1_rep, y1_rep, ibuf->x, ibuf->y, ibuf->rect_float);
2291                                                 }
2292                                                 else if(sima->flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels==1))) {
2293                                                         if(ibuf->zbuf)
2294                                                                 sima_draw_zbuf_pixels(x1_rep, y1_rep, ibuf->x, ibuf->y, ibuf->zbuf);
2295                                                         else if(ibuf->zbuf_float)
2296                                                                 sima_draw_zbuffloat_pixels(x1_rep, y1_rep, ibuf->x, ibuf->y, ibuf->zbuf_float);
2297                                                         else if(ibuf->channels==1)
2298                                                                 sima_draw_zbuffloat_pixels(x1_rep, y1_rep, ibuf->x, ibuf->y, ibuf->rect_float);
2299                                                 }
2300                                                 else {
2301                                                         if(sima->flag & SI_USE_ALPHA) {
2302                                                                 sima_draw_alpha_backdrop(sima, x1_rep, y1_rep, ibuf->x*xuser_asp, ibuf->y*yuser_asp);
2303                                                                 glEnable(GL_BLEND);
2304                                                                 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
2305                                                         }
2306                                                         
2307                                                         /* detect if we need to redo the curve map. 
2308                                                            ibuf->rect is zero for compositor and render results after change 
2309                                                            convert to 32 bits always... drawing float rects isnt supported well (atis)
2310                                                         
2311                                                            NOTE: if float buffer changes, we have to manually remove the rect
2312                                                         */
2313                                                         
2314                                                         if(ibuf->rect_float) {
2315                                                                 if(ibuf->rect==NULL) {
2316                                                                         if(image_curves_active(sa))
2317                                                                                 curvemapping_do_ibuf(G.sima->cumap, ibuf);
2318                                                                         else 
2319                                                                                 IMB_rect_from_float(ibuf);
2320                                                                 }
2321                                                         }
2322                 
2323                                                         if(ibuf->rect)
2324                                                                 glaDrawPixelsSafe(x1_rep, y1_rep, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
2325                 //                                      else
2326                 //                                              glaDrawPixelsSafe(x1_rep, y1_rep, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_FLOAT, ibuf->rect_float);
2327                                                         
2328                                                         if(sima->flag & SI_USE_ALPHA)
2329                                                                 glDisable(GL_BLEND);
2330                                                 }
2331                                                 
2332                                                 /* only draw once */
2333                                                 if(!loop_draw_ok) {
2334                                                         break; /* only draw once */
2335                                                 } else if ((PIL_check_seconds_timer() - time_current) > 0.25) {
2336                                                         loop_draw_ok = 0;
2337                                                         break;
2338                                                 }
2339                                 
2340                                 /* tile draw loop */
2341                                         }
2342                                         /* only draw once */
2343                                         if(!loop_draw_ok) break;
2344                                 }
2345                                 /* tile draw loop */
2346                                 
2347                         }
2348                         
2349                         brush= G.scene->toolsettings->imapaint.brush;
2350                         if(brush && (G.scene->toolsettings->imapaint.tool == PAINT_TOOL_CLONE)) {
2351                                 int w, h;
2352                                 unsigned char *clonerect;
2353
2354                                 /* this is not very efficient, but glDrawPixels doesn't allow
2355                                    drawing with alpha */
2356                                 clonerect= alloc_alpha_clone_image(&w, &h);
2357
2358                                 if(clonerect) {
2359                                         int offx, offy;
2360                                         offx = sima->zoom*ibuf->x * + brush->clone.offset[0];
2361                                         offy = sima->zoom*ibuf->y * + brush->clone.offset[1];
2362
2363                                         glEnable(GL_BLEND);
2364                                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2365                                         glaDrawPixelsSafe(x1 + offx, y1 + offy, w, h, w, GL_RGBA, GL_UNSIGNED_BYTE, clonerect);
2366                                         glDisable(GL_BLEND);
2367
2368                                         MEM_freeN(clonerect);
2369                                 }
2370                         }
2371                         
2372                         glPixelZoom(1.0, 1.0);
2373                         
2374                         if(show_viewer==0) { 
2375                                 draw_uvs_sima();
2376                                 drawcursor_sima(xuser_asp, yuser_asp);
2377                         }
2378                 }
2379
2380                 glPixelZoom(1.0, 1.0);
2381
2382                 calc_image_view(sima, 'f');     /* float */
2383         }
2384
2385         draw_image_transform(ibuf, xuser_asp, yuser_asp);
2386         
2387         /* draw grease-pencil ('image' strokes) */
2388         if (sima->flag & SI_DISPGP)
2389                 draw_gpencil_2dimage(sa, ibuf);
2390
2391         mywinset(sa->win);      /* restore scissor after gla call... */
2392         myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
2393         
2394         /* draw grease-pencil (screen strokes) */
2395         if (sima->flag & SI_DISPGP)
2396                 draw_gpencil_2dview(sa, 0);
2397
2398         if(G.rendering==0) {
2399                 draw_image_view_tool();
2400         }
2401         draw_area_emboss(sa);
2402
2403         /* it is important to end a view in a transform compatible with buttons */
2404         bwin_scalematrix(sa->win, sima->blockscale, sima->blockscale, sima->blockscale);
2405         if(!(G.rendering && show_render))
2406                 image_blockhandlers(sa);
2407
2408         sa->win_swap= WIN_BACK_OK;
2409 }
2410
2411 static void image_zoom_set_factor(float zoomfac)
2412 {
2413         SpaceImage *sima= curarea->spacedata.first;
2414         int width, height;
2415
2416         if (zoomfac <= 0.0f)
2417                 return;
2418
2419         sima->zoom *= zoomfac;
2420
2421         if (sima->zoom > 0.1f && sima->zoom < 4.0f)
2422                 return;
2423
2424         /* check zoom limits */
2425
2426         calc_image_view(G.sima, 'f'); /* was 'p' are there any cases where this should be 'p'?*/
2427         width= 256;
2428         height= 256;
2429         if (sima->image) {
2430                 ImBuf *ibuf= imagewindow_get_ibuf(sima);
2431
2432                 if (ibuf) {
2433                         float xim, yim;
2434                         /* I know a bit weak... but preview uses not actual image size */
2435                         if(image_preview_active(curarea, &xim, &yim)) {
2436                                 width= (int) xim;
2437                                 height= (int) yim;
2438                         }
2439                         else {
2440                                 width= ibuf->x;
2441                                 height= ibuf->y;
2442                         }
2443                 }
2444         }
2445         width *= sima->zoom;
2446         height *= sima->zoom;
2447
2448         if ((width < 4) && (height < 4))
2449                 sima->zoom /= zoomfac;
2450         else if((curarea->winrct.xmax - curarea->winrct.xmin) <= sima->zoom)
2451                 sima->zoom /= zoomfac;
2452         else if((curarea->winrct.ymax - curarea->winrct.ymin) <= sima->zoom)
2453                 sima->zoom /= zoomfac;
2454 }
2455
2456 void image_viewmove(int mode)
2457 {
2458         short mval[2], mvalo[2], zoom0;
2459         int oldcursor;
2460         Window *win;
2461         
2462         getmouseco_sc(mvalo);
2463         zoom0= G.sima->zoom;
2464         
2465         oldcursor=get_cursor();
2466         win=winlay_get_active_window();
2467         
2468         SetBlenderCursor(BC_NSEW_SCROLLCURSOR);
2469         
2470         while(get_mbut()&(L_MOUSE|M_MOUSE)) {
2471
2472                 getmouseco_sc(mval);
2473
2474                 if(mvalo[0]!=mval[0] || mvalo[1]!=mval[1]) {
2475                 
2476                         if(mode==0) {
2477                                 G.sima->xof += (mvalo[0]-mval[0])/G.sima->zoom;
2478                                 G.sima->yof += (mvalo[1]-mval[1])/G.sima->zoom;
2479                         }
2480                         else if (mode==1) {
2481                                 float factor;
2482
2483                                 factor= 1.0+(float)(mvalo[0]-mval[0]+mvalo[1]-mval[1])/300.0;
2484                                 image_zoom_set_factor(factor);
2485                         }
2486
2487                         mvalo[0]= mval[0];
2488                         mvalo[1]= mval[1];
2489                         
2490                         scrarea_do_windraw(curarea);
2491                         screen_swapbuffers();
2492                 }
2493                 else BIF_wait_for_statechange();
2494         }
2495         window_set_cursor(win, oldcursor);
2496         
2497         if(image_preview_active(curarea, NULL, NULL)) {
2498                 /* recalculates new preview rect */
2499                 scrarea_do_windraw(curarea);
2500                 image_preview_event(2);
2501         }
2502 }
2503
2504 void image_viewzoom(unsigned short event, int invert)
2505 {
2506         SpaceImage *sima= curarea->spacedata.first;
2507
2508         if(event==WHEELDOWNMOUSE || event==PADMINUS)
2509                 image_zoom_set_factor((U.uiflag & USER_WHEELZOOMDIR)? 1.25: 0.8);
2510         else if(event==WHEELUPMOUSE || event==PADPLUSKEY)
2511                 image_zoom_set_factor((U.uiflag & USER_WHEELZOOMDIR)? 0.8: 1.25);
2512         else if(event==PAD1)
2513                 sima->zoom= 1.0;
2514         else if(event==PAD2)
2515                 sima->zoom= (invert)? 2.0: 0.5;
2516         else if(event==PAD4)
2517                 sima->zoom= (invert)? 4.0: 0.25;
2518         else if(event==PAD8)
2519                 sima->zoom= (invert)? 8.0: 0.125;
2520         
2521         /* ensure pixel exact locations for draw */
2522         sima->xof= (int)sima->xof;
2523         sima->yof= (int)sima->yof;
2524         
2525         if(image_preview_active(curarea, NULL, NULL)) {
2526                 /* recalculates new preview rect */
2527                 scrarea_do_windraw(curarea);
2528                 image_preview_event(2);
2529         }
2530 }
2531
2532 /**
2533  * Updates the fields of the View2D member of the SpaceImage struct.
2534  * Default behavior is to reset the position of the image and set the zoom to 1
2535  * If the image will not fit within the window rectangle, the zoom is adjusted
2536  *
2537  * @return    void
2538  *   
2539  */
2540 void image_home(void)
2541 {
2542         ImBuf *ibuf;
2543         int width, height, imgwidth, imgheight;
2544         float zoomX, zoomY;
2545
2546         if (curarea->spacetype != SPACE_IMAGE) return;
2547         ibuf= imagewindow_get_ibuf(G.sima);
2548         
2549         if (ibuf == NULL) {
2550                 imgwidth = 256;
2551                 imgheight = 256;
2552         }
2553         else {
2554                 float xuser_asp, yuser_asp;
2555                 image_pixel_aspect(G.sima->image, &xuser_asp, &yuser_asp);
2556                 imgwidth = ibuf->x * xuser_asp;
2557                 imgheight = ibuf->y * yuser_asp;
2558         }
2559
2560         /* Check if the image will fit in the image with zoom==1 */
2561         width = curarea->winx;
2562         height = curarea->winy;
2563         if (((imgwidth >= width) || (imgheight >= height)) && 
2564                 ((width > 0) && (height > 0))) {
2565                 /* Find the zoom value that will fit the image in the image space */
2566                 zoomX = ((float)width) / ((float)imgwidth);
2567                 zoomY = ((float)height) / ((float)imgheight);
2568                 G.sima->zoom = 1.0f / power_of_2(1/ MIN2(zoomX, zoomY) );
2569         }
2570         else {
2571                 G.sima->zoom= 1.0f;
2572         }
2573
2574         G.sima->xof= G.sima->yof= 0.0f;
2575         
2576         calc_image_view(G.sima, 'f'); /* was 'p' are there any cases where this should be 'p'?*/
2577         /*calc_arearcts(curarea);*/
2578         scrarea_queue_winredraw(curarea);
2579         scrarea_queue_winredraw(curarea);
2580 }
2581
2582 void image_viewcenter(void)
2583 {
2584         ImBuf *ibuf= imagewindow_get_ibuf(G.sima);
2585         float size, min[2], max[2], d[2], xim=256.0f, yim=256.0f;
2586
2587         if( is_uv_tface_editing_allowed()==0 ) return;
2588
2589         if (!minmax_tface_uv(min, max)) return;
2590
2591         if(ibuf) {
2592                 xim= ibuf->x;
2593                 yim= ibuf->y;
2594         }
2595
2596         G.sima->xof= (int) (((min[0] + max[0])*0.5f - 0.5f)*xim);
2597         G.sima->yof= (int) (((min[1] + max[1])*0.5f - 0.5f)*yim);
2598
2599         d[0] = max[0] - min[0];
2600         d[1] = max[1] - min[1];
2601         size= 0.5*MAX2(d[0], d[1])*MAX2(xim, yim)/256.0f;
2602         
2603         if(size<=0.01) size= 0.01;
2604
2605         G.sima->zoom= 0.7/size;
2606
2607         calc_image_view(G.sima, 'f'); /* was 'p' are there any cases where 'p' is still needed? */
2608
2609         scrarea_queue_winredraw(curarea);
2610 }
2611
2612
2613 /* *********************** render callbacks ***************** */
2614
2615 /* set on initialize render, only one render output to imagewindow can exist, so the global isnt dangerous yet :) */
2616 static ScrArea *image_area= NULL;
2617
2618 /* can get as well the full picture, as the parts while rendering */
2619 static void imagewindow_progress(ScrArea *sa, RenderResult *rr, volatile rcti *renrect)
2620 {
2621         SpaceImage *sima= sa->spacedata.first;
2622         float x1, y1, *rectf= NULL;
2623         unsigned int *rect32= NULL;
2624         int ymin, ymax, xmin, xmax;
2625         
2626         /* if renrect argument, we only display scanlines */
2627         if(renrect) {
2628                 /* if ymax==recty, rendering of layer is ready, we should not draw, other things happen... */
2629                 if(rr->renlay==NULL || renrect->ymax>=rr->recty)
2630                         return;
2631                 
2632                 /* xmin here is first subrect x coord, xmax defines subrect width */
2633                 xmin = renrect->xmin;
2634                 xmax = renrect->xmax - xmin;
2635                 if (xmax<2) return;
2636                 
2637                 ymin= renrect->ymin;
2638                 ymax= renrect->ymax - ymin;
2639                 if(ymax<2)
2640                         return;
2641                 renrect->ymin= renrect->ymax;
2642         }
2643         else {
2644                 xmin = ymin = 0;
2645                 xmax = rr->rectx - 2*rr->crop;
2646                 ymax = rr->recty - 2*rr->crop;
2647         }
2648         
2649         /* image window cruft */
2650         
2651         /* find current float rect for display, first case is after composit... still weak */
2652         if(rr->rectf)
2653                 rectf= rr->rectf;
2654         else {
2655                 if(rr->rect32)
2656                         rect32= (unsigned int *)rr->rect32;
2657                 else {
2658                         if(rr->renlay==NULL || rr->renlay->rectf==NULL) return;
2659                         rectf= rr->renlay->rectf;
2660                 }
2661         }
2662         if(rectf) {
2663                 /* if scanline updates... */
2664                 rectf+= 4*(rr->rectx*ymin + xmin);
2665                 
2666                 /* when rendering more pixels than needed, we crop away cruft */
2667                 if(rr->crop)
2668                         rectf+= 4*(rr->crop*rr->rectx + rr->crop);
2669         }
2670         
2671         /* tilerect defines drawing offset from (0,0) */
2672         /* however, tilerect (xmin, ymin) is first pixel */
2673         x1 = sima->centx + (rr->tilerect.xmin + rr->crop + xmin)*sima->zoom;
2674         y1 = sima->centy + (rr->tilerect.ymin + rr->crop + ymin)*sima->zoom;
2675         
2676         /* needed for gla draw */
2677         { rcti rct= sa->winrct; rct.ymax-= RW_HEADERY; glaDefine2DArea(&rct);}
2678
2679         glPixelZoom(sima->zoom, sima->zoom);
2680         
2681         if(rect32)
2682                 glaDrawPixelsSafe(x1, y1, xmax, ymax, rr->rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect32);
2683         else
2684                 glaDrawPixelsSafe_to32(x1, y1, xmax, ymax, rr->rectx, rectf);
2685         
2686         glPixelZoom(1.0, 1.0);
2687         
2688 }
2689
2690
2691 /* in render window; display a couple of scanlines of rendered image */
2692 /* NOTE: called while render, so no malloc allowed! */
2693 static void imagewindow_progress_display_cb(RenderResult *rr, volatile rcti *rect)
2694 {
2695         
2696         if (image_area) {
2697                 
2698                 imagewindow_progress(image_area, rr, rect);
2699
2700                 /* no screen_swapbuffers, prevent any other window to draw */
2701                 myswapbuffers();
2702         }
2703 }
2704
2705 /* unused, init_display_cb is called on each render */
2706 static void imagewindow_clear_display_cb(RenderResult *rr)
2707 {
2708         if (image_area) {
2709         }
2710 }
2711
2712 /* returns biggest area that is not uv/image editor. Note that it uses buttons */
2713 /* window as the last possible alternative.                                                                        */
2714 static ScrArea *biggest_non_image_area(void)
2715 {
2716         ScrArea *sa, *big= NULL;
2717         int size, maxsize= 0, bwmaxsize= 0;
2718         short foundwin= 0;
2719         
2720         for(sa= G.curscreen->areabase.first; sa; sa= sa->next) {
2721                 if(sa->winx > 10 && sa->winy > 10) {
2722                         size= sa->winx*sa->winy;
2723                         if(sa->spacetype == SPACE_BUTS) {
2724                                 if(foundwin == 0 && size > bwmaxsize) {
2725                                         bwmaxsize= size;
2726                                         big= sa;        
2727                                 }
2728                         }
2729                         else if(sa->spacetype != SPACE_IMAGE && size > maxsize) {
2730                                 maxsize= size;
2731                                 big= sa;
2732                                 foundwin= 1;
2733                         }
2734                 }
2735         }
2736                 
2737         return big;
2738 }
2739
2740 static ScrArea *biggest_area(void)
2741 {
2742         ScrArea *sa, *big= NULL;
2743         int size, maxsize= 0;
2744         
2745         for(sa= G.curscreen->areabase.first; sa; sa= sa->next) {
2746                 size= sa->winx*sa->winy;
2747                 if(size > maxsize) {
2748                         maxsize= size;
2749                         big= sa;
2750                 }
2751         }
2752         return big;
2753 }
2754
2755
2756 /* if R_DISPLAYIMAGE
2757       use Image Window showing Render Result
2758           else: turn largest non-image area into Image Window (not to frustrate texture or composite usage)
2759           else: then we use Image Window anyway...
2760    if R_DISPSCREEN
2761       make a new temp fullscreen area with Image Window
2762 */
2763
2764 static ScrArea *find_area_showing_r_result(void)
2765 {
2766         ScrArea *sa;
2767         SpaceImage *sima;
2768         
2769         /* find an imagewindow showing render result */
2770         for(sa=G.curscreen->areabase.first; sa; sa= sa->next) {
2771                 if(sa->spacetype==SPACE_IMAGE) {
2772                         sima= sa->spacedata.first;
2773                         if(sima->image && sima->image->type==IMA_TYPE_R_RESULT)
2774                                 break;
2775                 }
2776         }
2777         return sa;
2778 }
2779
2780 static ScrArea *imagewindow_set_render_display(void)
2781 {
2782         ScrArea *sa;
2783         SpaceImage *sima;
2784         
2785         sa= find_area_showing_r_result();
2786         
2787         if(sa==NULL) {
2788                 /* find largest open non-image area */
2789                 sa= biggest_non_image_area();
2790                 if(sa) {
2791                         newspace(sa, SPACE_IMAGE);
2792                         sima= sa->spacedata.first;
2793                         
2794                         /* makes ESC go back to prev space */
2795                         sima->flag |= SI_PREVSPACE;
2796                 }
2797                 else {
2798                         /* use any area of decent size */
2799                         sa= biggest_area();
2800                         if(sa->spacetype!=SPACE_IMAGE) {
2801                                 newspace(sa, SPACE_IMAGE);
2802                                 sima= sa->spacedata.first;
2803                                 
2804                                 /* makes ESC go back to prev space */
2805                                 sima->flag |= SI_PREVSPACE;
2806                         }
2807                 }
2808         }
2809         
2810         sima= sa->spacedata.first;
2811         
2812         /* get the correct image, and scale it */
2813         sima->image= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
2814         
2815         if(G.displaymode==R_DISPLAYSCREEN) {
2816                 if(sa->full==0) {
2817                         sima->flag |= SI_FULLWINDOW;
2818                         /* fullscreen works with lousy curarea */
2819                         curarea= sa;
2820                         area_fullscreen();
2821                         sa= curarea;
2822                 }
2823         }
2824         
2825         return sa;
2826 }
2827
2828 static void imagewindow_init_display_cb(RenderResult *rr)
2829 {
2830         
2831         image_area= imagewindow_set_render_display();
2832         
2833         if(image_area) {
2834                 SpaceImage *sima= image_area->spacedata.first;
2835                 
2836                 areawinset(image_area->win);
2837                 
2838                 /* calc location using original size (tiles don't tell) */
2839                 sima->centx= (image_area->winx - sima->zoom*(float)rr->rectx)/2.0f;
2840                 sima->centy= (image_area->winy - sima->zoom*(float)rr->recty)/2.0f;
2841                 
2842                 sima->centx-= sima->zoom*sima->xof;
2843                 sima->centy-= sima->zoom*sima->yof;
2844                 
2845                 drawimagespace(image_area, sima);
2846                 if(image_area->headertype) scrarea_do_headdraw(image_area);
2847
2848                 /* no screen_swapbuffers, prevent any other window to draw */
2849                 myswapbuffers();
2850                 
2851                 allqueue(REDRAWIMAGE, 0);       /* redraw in end */
2852         }
2853 }
2854
2855 /* coming from BIF_toggle_render_display() */
2856 void imagewindow_toggle_render(void)
2857 {
2858         ScrArea *sa;
2859         
2860         /* check if any imagewindow is showing temporal render output */
2861         for(sa=G.curscreen->areabase.first; sa; sa= sa->next) {
2862                 if(sa->spacetype==SPACE_IMAGE) {
2863                         SpaceImage *sima= sa->spacedata.first;
2864                         
2865                         if(sima->image && sima->image->type==IMA_TYPE_R_RESULT)
2866                                 if(sima->flag & (SI_PREVSPACE|SI_FULLWINDOW))
2867                                         break;
2868                 }
2869         }
2870         if(sa) {
2871                 addqueue(sa->win, ESCKEY, 1);   /* also returns from fullscreen */
2872         }
2873         else {
2874                 sa= imagewindow_set_render_display();
2875                 scrarea_queue_headredraw(sa);
2876                 scrarea_queue_winredraw(sa);
2877         }
2878 }
2879
2880 /* NOTE: called while render, so no malloc allowed! */
2881 static void imagewindow_renderinfo_cb(RenderStats *rs)
2882 {
2883         
2884         if(image_area) {
2885                 BIF_make_render_text(rs);
2886
2887                 imagewindow_draw_renderinfo(image_area);
2888                 
2889                 /* no screen_swapbuffers, prevent any other window to draw */
2890                 myswapbuffers();
2891         }
2892 }
2893
2894 void imagewindow_render_callbacks(Render *re)
2895 {
2896         RE_display_init_cb(re, imagewindow_init_display_cb);
2897         RE_display_draw_cb(re, imagewindow_progress_display_cb);
2898         RE_display_clear_cb(re, imagewindow_clear_display_cb);
2899         RE_stats_draw_cb(re, imagewindow_renderinfo_cb);        
2900 }
2901