New feature! (Well, replacement for the exisiting cumbersome "DispView")
authorTon Roosendaal <ton@blender.org>
Mon, 12 Jun 2006 14:39:08 +0000 (14:39 +0000)
committerTon Roosendaal <ton@blender.org>
Mon, 12 Jun 2006 14:39:08 +0000 (14:39 +0000)
Next to the "DispWindow" there are now two new choices:

- Display render output to Image Editor
- Display render output to Screen-sized Image Editor

Both options won't open a 2nd window anymore, which makes work quite more
smooth even, especially because 'focus' isn't lost. Further it fits in the
'single window UI' paradigm of Blender. Should have been done 10 years ago!

Lastly it might bypass issues with X11... having 2 windows with opengl
context is not always stable in Linux.

This option uses an identical trick as for the Compositor viewer, using an
Image block with a fixed name ("Render Result").

The flow, when invoking a Render, goes as follows:
- first it checks if there's an Image Editor visible displaying the "Render
  Result", if so then it uses that area-window.
   (Use this option for dual-monitor setups for example, a render will always
   go to the same location then)
- else it checks if there's an Image Editor open in general, it then
  assigns that window the "Render Result" Image.
- else: it searches for the largest Area in the screen, and turns that into
  a temporal Image Editor showing render output.

After a render, an ESC will push back the former view, if the Area type has
changed.

Same rules apply for the "Full Screen" option. Here an ESC will always go
back to the regular Screen, and restore Area type if required.

While rendering, the queue for the renderwindow isn't handled yet, so you can
not zoom (nor get full redraws), as for the regular render window.

Existing conflicts:
- in FaceSelect mode, the Image editor enforces to display the face texture
  after rendering again.
- when using an Image window for compositing, you'll lose the Viewer output
  on a render.

Implementation note:
While rendering updates, nothing is drawn in frontbuffer anymore. That's
good news for b0rked OpenGL drivers (and faster). However, for the few
OpenGL cards that don't do a "swap copy" but a "swap exchange" you get
issues... has to be worked on. I'm afraid we have to drop frontbuffer
drawing altogether.

Other fixes:

- Hotkeys NumPad 1, 2, 4, 8 will set zoom levels (was half coded only?)
  Use SHIFT to zoom out (smaller).

- Rendering Tile updates still had draw errors on edges of tiles, in OSA
  only. (Caused by commit 4 days ago)

13 files changed:
source/blender/blenloader/intern/readfile.c
source/blender/include/BIF_drawimage.h
source/blender/include/BIF_renderwin.h
source/blender/include/blendef.h
source/blender/makesdna/DNA_space_types.h
source/blender/python/api2_2x/sceneRender.c
source/blender/render/intern/source/pipeline.c
source/blender/src/buttons_scene.c
source/blender/src/drawimage.c
source/blender/src/editscreen.c
source/blender/src/header_image.c
source/blender/src/renderwin.c
source/blender/src/space.c

index e53d4cb4ba8c28619e238280896c84e998ec4984..c9a90d0dc02d8d9851ee84ceae2d5f39a8f8826a 100644 (file)
@@ -1947,8 +1947,8 @@ static void lib_link_image(FileData *fd, Main *main)
 
 static void direct_link_image(FileData *fd, Image *ima)
 {
-       ima->ibuf= 0;
-       ima->anim= 0;
+       ima->ibuf= NULL;
+       ima->anim= NULL;
        memset(ima->mipmap, 0, sizeof(ima->mipmap));
        ima->repbind= 0;
        ima->bindcode= 0;
@@ -3303,6 +3303,7 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                                sima->cumap= newdataadr(fd, sima->cumap);
                                if(sima->cumap)
                                        direct_link_curvemapping(fd, sima->cumap);
+                               sima->info_str= NULL;
                        }
                        else if(sl->spacetype==SPACE_NODE) {
                                SpaceNode *snode= (SpaceNode *)sl;
index 0435522025b881adff8cd5baeec10211ec06d652..a3b12b7bafdc093a3e2d1478f24848591b456f4b 100644 (file)
@@ -35,6 +35,7 @@
 
 struct ScrArea;
 struct SpaceImage;
+struct Render;
 
 void do_imagebuts(unsigned short event);
 void calc_image_view(struct SpaceImage *sima, char mode);
@@ -50,5 +51,8 @@ void uvco_to_areaco_noclip(float *vec, int *mval);
 void what_image(struct SpaceImage *sima);
 void image_preview_event(int event);
 
+void imagewindow_render_callbacks(struct Render *re);
+void imagewindow_toggle_render(void);
+
 #endif
 
index eeb48ad8c27794fe8d9d965039e9a13a9b31d2b0..dad4f36412cbbb28946445f7e0ca9fa705bcf4e1 100644 (file)
@@ -31,6 +31,7 @@
  */
 
 struct ScrArea;
+struct RenderStats;
 
 void calc_renderwin_rectangle(int rectx, int recty, int posmask, int renderpos_r[2], int rendersize_r[2]);
 
@@ -50,3 +51,12 @@ void BIF_redraw_render_rect(void);
 void BIF_swap_render_rects(void);
 void BIF_toggle_render_display(void);
 
+/* should not be here, ~WIP~ */
+void make_renderinfo_string(struct RenderStats *rs, char *str);
+
+/* space for info text */
+#define RW_HEADERY             18
+
+/* header print for window */
+#define RW_MAXTEXT             512
+
index 425d95cc112ce5752df0b080d4d9eb29d0f6029c..0b2ca31a5798081ffc07c5127d02c7206b6a02e9 100644 (file)
 #define B_MESH_X_MIRROR        0x100
 
 /* DISPLAYMODE */
-#define R_DISPLAYVIEW  0
+#define R_DISPLAYIMAGE 0
 #define R_DISPLAYWIN   1
-#define R_DISPLAYAUTO  2
+#define R_DISPLAYSCREEN        2
 
        /* Gvp.flag and Gwp.flag */
 #define VP_COLINDEX    1
index 946f40eafa6a594027fc17d6d5398f1a3cb6dd6f..14fc8a928ac37a0b0055e4cb2801c6cee2f8c5b5 100644 (file)
@@ -223,11 +223,17 @@ typedef struct SpaceImage {
        
        struct Image *image;
        struct CurveMapping *cumap;
-       float zoom;
        short mode, menunr;
        short imanr, curtile;
-       float xof, yof;
-       short flag, lock;
+       int flag;
+       short pad1, lock;
+       
+       float zoom, pad2;
+       
+       float xof, yof;                 /* user defined offset, image is centered */
+       
+       float centx, centy;             /* storage for offset while render drawing */
+       char *info_str;                 /* info string for render */
 } SpaceImage;
 
 typedef struct SpaceNla{
@@ -469,10 +475,12 @@ typedef struct SpaceImaSel {
 #define SI_COORDFLOATS  512
 #define SI_PIXELSNAP   1024
 #define SI_LIVE_UNWRAP 2048
-#define SI_USE_ALPHA   4096
-#define SI_SHOW_ALPHA  8192
-#define SI_SHOW_ZBUF   16384
-
+#define SI_USE_ALPHA   0x1000
+#define SI_SHOW_ALPHA  0x2000
+#define SI_SHOW_ZBUF   0x4000
+               /* next two for render window dislay */
+#define SI_PREVSPACE   0x8000
+#define SI_FULLWINDOW  0x10000
 
 /* SpaceText flags (moved from DNA_text_types.h) */
 
index 8387b2a8d08a21f8d78677f70adadb7e7e44b529..99b923d4eb4fe89804fb201d559b4cb4a1de2887 100644 (file)
@@ -351,7 +351,7 @@ PyObject *M_Render_SetRenderWinPos( PyObject * self, PyObject * args )
 
 PyObject *M_Render_EnableDispView( PyObject * self )
 {
-       G.displaymode = R_DISPLAYVIEW;
+       G.displaymode = R_DISPLAYIMAGE;
        EXPP_allqueue( REDRAWBUTSSCENE, 0 );
 
        return EXPP_incr_ret( Py_None );
@@ -1850,7 +1850,7 @@ static int RenderData_setDisplayMode( BPy_RenderData *self,
                PyObject *value )
 {
        return EXPP_setIValueRange( value, &G.displaymode,
-                       R_DISPLAYVIEW, R_DISPLAYWIN, 'h' );
+                       R_DISPLAYIMAGE, R_DISPLAYWIN, 'h' );
 }
 
 static PyObject *RenderData_getRenderPath( BPy_RenderData * self )
index 8b34970309bb13fa7418b999555560749780bc05..57c815878ae6f682a88f2490198797dfd44a3ef4 100644 (file)
@@ -367,7 +367,7 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int
        rr= MEM_callocT(sizeof(RenderResult), "new render result");
        rr->rectx= rectx;
        rr->recty= recty;
-       rr->renrect.xmin= 0; rr->renrect.xmax= rectx;
+       rr->renrect.xmin= 0; rr->renrect.xmax= rectx-2*crop;
        /* crop is one or two extra pixels rendered for filtering, is used for merging and display too */
        rr->crop= crop;
        
index ca061acdd336b54d155eb6236df01ffce70394c1..c2f5f84199bb2cf3a2fff1c02f3414e7546e038c 100644 (file)
@@ -1216,10 +1216,8 @@ static void render_panel_output(void)
 
        uiDefButBitS(block, TOG, R_EXR_TILE_FILE, B_NOP, "Save Buffers", 72, 31, 120, 19, &G.scene->r.scemode, 0.0, 0.0, 0, 0, "Save the tiles for all RenderLayers and used SceneNodes to files, to save memory");
        
-       uiBlockBeginAlign(block);
-       uiDefButS(block, ROW, B_REDR, "DispWin",        72, 10, 60, 20, &G.displaymode, 0.0, (float)R_DISPLAYWIN, 0, 0, "Sets render output to display in a separate window");
-       uiDefButS(block, ROW, B_REDR, "DispView",       134, 10, 60, 20, &G.displaymode, 0.0, (float)R_DISPLAYVIEW, 0, 0, "Sets render output to display in 3D view");
-       uiBlockEndAlign(block);
+       uiDefButS(block, MENU, B_REDR, "Render Display %t|Render Window %x1|Image Editor %x0|Full Screen %x2",  
+                                       72, 10, 120, 19, &G.displaymode, 0.0, (float)R_DISPLAYWIN, 0, 0, "Sets render output display");
 
        uiDefButBitS(block, TOG, R_EXTENSION, B_NOP, "Extensions", 205, 10, 105, 19, &G.scene->r.scemode, 0.0, 0.0, 0, 0, "Adds extensions to the output when rendering animations");
 
index ede7210df3f46674149c27eb1c62ff426c210316..d67a0bc7931726377e4e693cfc13db588ac4daa0 100644 (file)
@@ -87,6 +87,7 @@
 #include "BIF_interface_icons.h"
 #include "BIF_editsima.h"
 #include "BIF_glutil.h"
+#include "BIF_renderwin.h"
 #include "BIF_space.h"
 #include "BIF_screen.h"
 #include "BIF_transform.h"
@@ -96,6 +97,9 @@
 #include "BSE_trans_types.h"
 #include "BSE_view.h"
 
+#include "RE_pipeline.h"
+#include "BMF_Api.h"
+
 /* Modules used */
 #include "mydevice.h"
 #include "blendef.h"
@@ -187,9 +191,16 @@ void calc_image_view(SpaceImage *sima, char mode)
        float zoom;
        
        if(image_preview_active(curarea, &xim, &yim));
-       else if(sima->image && sima->image->ibuf) {
-               xim= sima->image->ibuf->x;
-               yim= sima->image->ibuf->y;
+       else if(sima->image) {
+               if(sima->image->ibuf) {
+                       xim= sima->image->ibuf->x;
+                       yim= sima->image->ibuf->y;
+               }
+               else if( strcmp(sima->image->name, "Render Result")==0 ) {
+                       /* not very important, just nice */
+                       xim= (G.scene->r.xsch*G.scene->r.size)/100;
+                       yim= (G.scene->r.ysch*G.scene->r.size)/100;
+               }
        }
                
        sima->v2d.tot.xmin= 0;
@@ -229,21 +240,23 @@ void calc_image_view(SpaceImage *sima, char mode)
        }
 }
 
+/* check for facelesect, and set active image */
 void what_image(SpaceImage *sima)
 {
        TFace *activetf;
        Mesh *me;
                
        if(sima->mode==SI_TEXTURE) {
-               if(G.f & G_FACESELECT) {
-
+               
+               if((G.f & G_FACESELECT) && G.rendering==0) {
+                       
                        sima->image= 0;
                        me= get_mesh(OBACT);
                        activetf = get_active_tface();
                        
                        if(me && me->tface && activetf && activetf->mode & TF_TEX) {
                                sima->image= activetf->tpage;
-                                       
+                               
                                if(sima->flag & SI_EDITTILE);
                                else sima->curtile= activetf->tile;
                                
@@ -254,6 +267,24 @@ void what_image(SpaceImage *sima)
                                }
                        }
                }
+               else if(sima->image && strcmp(sima->image->name, "Render Result")==0) {
+                       RenderResult rres;
+                       /* make ibuf if needed, and initialize it */
+                       
+                       /* allocate for each redraw, we don't want render result pointers hanging around */
+                       IMB_freeImBuf(sima->image->ibuf);
+                       sima->image->ibuf= NULL;
+                       
+                       RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres);
+                       if(rres.rectf || rres.rect32) {
+                               ImBuf *ibuf= sima->image->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, 0, 0);
+                               
+                               ibuf->x= rres.rectx;
+                               ibuf->y= rres.recty;
+                               ibuf->rect= rres.rect32;
+                               ibuf->rect_float= rres.rectf;
+                       }
+               }
        }
 }
 
@@ -1175,6 +1206,12 @@ static void imagespace_grid(SpaceImage *sima)
        
        gridsize= sima->zoom;
        
+       calc_image_view(sima, 'f');
+       myortho2(sima->v2d.cur.xmin, sima->v2d.cur.xmax, sima->v2d.cur.ymin, sima->v2d.cur.ymax);
+       
+       BIF_ThemeColorShade(TH_BACK, 20);
+       glRectf(0.0, 0.0, 1.0, 1.0);
+       
        if(gridsize<=0.0f) return;
        
        if(gridsize<1.0f) {
@@ -1349,14 +1386,38 @@ static void sima_draw_zbuffloat_pixels(float x1, float y1, int rectx, int recty,
        MEM_freeN(rectf);
 }
 
+static void imagewindow_draw_renderinfo(ScrArea *sa)
+{
+       SpaceImage *sima= sa->spacedata.first;
+       rcti rect;
+       float colf[3];
+       
+       if(sima->info_str==NULL)
+               return;
+       
+       rect= sa->winrct;
+       rect.ymin= rect.ymax-RW_HEADERY;
+       
+       glaDefine2DArea(&rect);
+       
+       /* clear header rect */
+       BIF_GetThemeColor3fv(TH_BACK, colf);
+       glClearColor(colf[0], colf[1], colf[2], 1.0); 
+       glClear(GL_COLOR_BUFFER_BIT);
+       
+       BIF_ThemeColor(TH_TEXT_HI);
+       glRasterPos2i(12, 5);
+       BMF_DrawString(G.fonts, sima->info_str);
+}
+
 void drawimagespace(ScrArea *sa, void *spacedata)
 {
        SpaceImage *sima= spacedata;
        ImBuf *ibuf= NULL;
        float col[3];
        unsigned int *rect;
-       int x1, y1;
-       short sx, sy, dx, dy;
+       float x1, y1;
+       short sx, sy, dx, dy, show_render= 0;
        
                /* If derived data is used then make sure that object
                 * is up-to-date... might not be the case because updates
@@ -1374,29 +1435,30 @@ void drawimagespace(ScrArea *sa, void *spacedata)
        bwin_clear_viewmat(sa->win);    /* clear buttons view */
        glLoadIdentity();
        
+       if(sima->image && strcmp(sima->image->name, "Render Result")==0 )
+               show_render= 1;
+       
        what_image(sima);
        
        if(sima->image) {
                if(sima->image->ibuf==NULL) {
                        load_image(sima->image, IB_rect, G.sce, G.scene->r.cfra);
                        scrarea_queue_headredraw(sa);   /* update header for image options */
-               }       
+               }
+               
                tag_image_time(sima->image);
                ibuf= sima->image->ibuf;
        }
        
        if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
-               calc_image_view(sima, 'f');
-               myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
-               BIF_ThemeColorShade(TH_BACK, 20);
-               glRectf(0.0, 0.0, 1.0, 1.0);
                imagespace_grid(sima);
-               draw_tfaces();
+               if(show_render==0)
+                       draw_tfaces();
        }
        else {
                float xim, yim, xoffs=0.0f, yoffs= 0.0f;
                
-               if(image_preview_active(curarea, &xim, &yim)) {
+               if(image_preview_active(sa, &xim, &yim)) {
                        xoffs= G.scene->r.disprect.xmin;
                        yoffs= G.scene->r.disprect.ymin;
                        glColor3ub(0,0,0);
@@ -1410,14 +1472,23 @@ void drawimagespace(ScrArea *sa, void *spacedata)
                }
                
                /* calc location */
-               x1= sima->zoom*xoffs + (curarea->winx-sima->zoom*xim)/2;
-               y1= sima->zoom*yoffs + (curarea->winy-sima->zoom*yim)/2;
+               x1= sima->zoom*xoffs + ((float)sa->winx - sima->zoom*(float)xim)/2.0f;
+               y1= sima->zoom*yoffs + ((float)sa->winy - sima->zoom*(float)yim)/2.0f;
        
                x1-= sima->zoom*sima->xof;
                y1-= sima->zoom*sima->yof;
                
                /* needed for gla draw */
-               glaDefine2DArea(&curarea->winrct);
+               if(show_render) { 
+                       rcti rct= sa->winrct; 
+                       
+                       imagewindow_draw_renderinfo(sa);        /* calls glaDefine2DArea too */
+                       
+                       rct.ymax-=RW_HEADERY; 
+                       glaDefine2DArea(&rct);
+               }
+               else glaDefine2DArea(&sa->winrct);
+               
                glPixelZoom((float)sima->zoom, (float)sima->zoom);
                                
                if(sima->flag & SI_EDITTILE) {
@@ -1474,7 +1545,6 @@ void drawimagespace(ScrArea *sa, void *spacedata)
                        }
                        else {
                                /* this part is generic image display */
-                               
                                if(sima->flag & SI_SHOW_ALPHA) {
                                        if(ibuf->rect)
                                                sima_draw_alpha_pixels(x1, y1, ibuf->x, ibuf->y, ibuf->rect);
@@ -1540,9 +1610,12 @@ void drawimagespace(ScrArea *sa, void *spacedata)
                        
                        glPixelZoom(1.0, 1.0);
                        
-                       draw_tfaces();
+                       if(show_render==0) 
+                               draw_tfaces();
                }
-       
+
+               glPixelZoom(1.0, 1.0);
+
                calc_image_view(sima, 'f');     /* float */
        }
 
@@ -1551,15 +1624,18 @@ void drawimagespace(ScrArea *sa, void *spacedata)
        mywinset(sa->win);      /* restore scissor after gla call... */
        myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
 
-       draw_image_view_tool();
-       draw_image_view_icon();
+       if(show_render==0) {
+               draw_image_view_tool();
+               draw_image_view_icon();
+       }
        draw_area_emboss(sa);
 
        /* it is important to end a view in a transform compatible with buttons */
        bwin_scalematrix(sa->win, sima->blockscale, sima->blockscale, sima->blockscale);
-       image_blockhandlers(sa);
+       if(!(G.rendering && show_render))
+               image_blockhandlers(sa);
 
-       curarea->win_swap= WIN_BACK_OK;
+       sa->win_swap= WIN_BACK_OK;
 }
 
 static void image_zoom_power_of_two(void)
@@ -1673,6 +1749,10 @@ void image_viewzoom(unsigned short event, int invert)
        else if(event==PAD8)
                sima->zoom= (invert)? 8.0: 0.125;
        
+       /* ensure pixel exact locations for draw */
+       sima->xof= (int)sima->xof;
+       sima->yof= (int)sima->yof;
+       
        if(image_preview_active(curarea, NULL, NULL)) {
                /* recalculates new preview rect */
                scrarea_do_windraw(curarea);
@@ -1695,7 +1775,7 @@ void image_home(void)
 
        if (curarea->spacetype != SPACE_IMAGE) return;
 
-       if ((G.sima->image == 0) || (G.sima->image->ibuf == 0)) {
+       if ((G.sima->image == NULL) || (G.sima->image->ibuf == NULL)) {
                imgwidth = 256;
                imgheight = 256;
        }
@@ -1717,10 +1797,10 @@ void image_home(void)
                image_zoom_power_of_two();
        }
        else {
-               G.sima->zoom= (float)1;
+               G.sima->zoom= 1.0f;
        }
 
-       G.sima->xof= G.sima->yof= 0;
+       G.sima->xof= G.sima->yof= 0.0f;
        
        calc_image_view(G.sima, 'p');
        
@@ -1740,8 +1820,8 @@ void image_viewcentre(void)
                yim= G.sima->image->ibuf->y;
        }
 
-       G.sima->xof= ((min[0] + max[0])*0.5f - 0.5f)*xim;
-       G.sima->yof= ((min[1] + max[1])*0.5f - 0.5f)*yim;
+       G.sima->xof= (int) (((min[0] + max[0])*0.5f - 0.5f)*xim);
+       G.sima->yof= (int) (((min[1] + max[1])*0.5f - 0.5f)*yim);
 
        d[0] = max[0] - min[0];
        d[1] = max[1] - min[1];
@@ -1756,3 +1836,260 @@ void image_viewcentre(void)
        scrarea_queue_winredraw(curarea);
 }
 
+
+/* *********************** render callbacks ***************** */
+
+/* set on initialize render, only one render output to imagewindow can exist, so the global isnt dangerous yet :) */
+static ScrArea *image_area= NULL;
+
+/* can get as well the full picture, as the parts while rendering */
+static void imagewindow_progress(ScrArea *sa, RenderResult *rr, volatile rcti *renrect)
+{
+       SpaceImage *sima= sa->spacedata.first;
+       float x1, y1, *rectf= NULL;
+       unsigned int *rect32= NULL;
+       int ymin, ymax, xmin, xmax;
+       
+       /* if renrect argument, we only display scanlines */
+       if(renrect) {
+               /* if ymax==recty, rendering of layer is ready, we should not draw, other things happen... */
+               if(rr->renlay==NULL || renrect->ymax>=rr->recty)
+                       return;
+               
+               /* xmin here is first subrect x coord, xmax defines subrect width */
+               xmin = renrect->xmin;
+               xmax = renrect->xmax - xmin;
+               if (xmax<2) return;
+               
+               ymin= renrect->ymin;
+               ymax= renrect->ymax - ymin;
+               if(ymax<2)
+                       return;
+               renrect->ymin= renrect->ymax;
+       }
+       else {
+               xmin = ymin = 0;
+               xmax = rr->rectx - 2*rr->crop;
+               ymax = rr->recty - 2*rr->crop;
+       }
+       
+       /* image window cruft */
+       
+       /* find current float rect for display, first case is after composit... still weak */
+       if(rr->rectf)
+               rectf= rr->rectf;
+       else {
+               if(rr->rect32)
+                       rect32= rr->rect32;
+               else {
+                       if(rr->renlay==NULL || rr->renlay->rectf==NULL) return;
+                       rectf= rr->renlay->rectf;
+               }
+       }
+       if(rectf) {
+               /* if scanline updates... */
+               rectf+= 4*(rr->rectx*ymin + xmin);
+               
+               /* when rendering more pixels than needed, we crop away cruft */
+               if(rr->crop)
+                       rectf+= 4*(rr->crop*rr->rectx + rr->crop);
+       }
+       
+       /* tilerect defines drawing offset from (0,0) */
+       /* however, tilerect (xmin, ymin) is first pixel */
+       x1 = sima->centx + (rr->tilerect.xmin + rr->crop + xmin)*sima->zoom;
+       y1 = sima->centy + (rr->tilerect.ymin + rr->crop + ymin)*sima->zoom;
+       
+       /* needed for gla draw */
+       { rcti rct= sa->winrct; rct.ymax-= RW_HEADERY; glaDefine2DArea(&rct);}
+
+       glPixelZoom((float)sima->zoom, (float)sima->zoom);
+       
+       if(rect32)
+               glaDrawPixelsSafe(x1, y1, xmax, ymax, rr->rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect32);
+       else
+               glaDrawPixelsSafe(x1, y1, xmax, ymax, rr->rectx, GL_RGBA, GL_FLOAT, rectf);
+       
+       glPixelZoom(1.0, 1.0);
+       
+}
+
+
+/* in render window; display a couple of scanlines of rendered image */
+static void imagewindow_progress_display_cb(RenderResult *rr, volatile rcti *rect)
+{
+       
+       if (image_area) {
+               imagewindow_progress(image_area, rr, rect);
+               image_area->win_swap= WIN_BACK_OK;
+               screen_swapbuffers();
+       }
+}
+
+/* unused, init_display_cb is called on each render */
+static void imagewindow_clear_display_cb(RenderResult *rr)
+{
+       if (image_area) {
+       }
+}
+
+static ScrArea *biggest_area(void)
+{
+       ScrArea *sa, *big= NULL;
+       int size, maxsize= 0;
+       
+       for(sa= G.curscreen->areabase.first; sa; sa= sa->next) {
+               size= sa->winx*sa->winy;
+               if(size > maxsize) {
+                       maxsize= size;
+                       big= sa;
+               }
+       }
+       return big;
+}
+
+
+/* if R_DISPLAYIMAGE
+      use Image Window showing Render Result
+      or: use largest Image Window
+         else: turn largest 3d view into Image Window
+   if R_DISPSCREEN
+      make a new temp fullscreen area with Image Window
+*/
+
+static ScrArea *imagewindow_set_render_display(void)
+{
+       ScrArea *sa;
+       SpaceImage *sima;
+       
+       /* find an imagewindow showing render result */
+       for(sa=G.curscreen->areabase.first; sa; sa= sa->next) {
+               if(sa->spacetype==SPACE_IMAGE) {
+                       sima= sa->spacedata.first;
+                       
+                       if(sima->image && strcmp(sima->image->name, "Render Result")==0 )
+                               break;
+               }
+       }
+       if(sa==NULL) {
+               /* find an open image window */
+               for(sa=G.curscreen->areabase.first; sa; sa= sa->next)
+                       if(sa->spacetype==SPACE_IMAGE)
+                               break;
+               
+               if(sa==NULL) {
+                       
+                       /* find largest open area */
+                       sa= biggest_area();
+                       newspace(sa, SPACE_IMAGE);
+                       sima= sa->spacedata.first;
+                       
+                       /* makes ESC go back to prev space */
+                       sima->flag |= SI_PREVSPACE;
+               }
+       }
+       
+       sima= sa->spacedata.first;
+       
+       /* get the correct image, and scale it */
+       sima->image = (Image *)find_id("IM", "Render Result");
+       
+       if(sima->image==NULL) {
+               Image *ima= alloc_libblock(&G.main->image, ID_IM, "Render Result");
+               strcpy(ima->name, "Render Result");
+               ima->ok= 1;
+               ima->xrep= ima->yrep= 1;
+               sima->image= ima;
+       }
+       
+       if(G.displaymode==R_DISPLAYSCREEN) {
+               if(sa->full==0) {
+                       sima->flag |= SI_FULLWINDOW;
+                       /* fullscreen works with lousy curarea */
+                       curarea= sa;
+                       area_fullscreen();
+                       sa= curarea;
+               }
+       }
+       
+       return sa;
+}
+
+static void imagewindow_init_display_cb(RenderResult *rr)
+{
+       
+       image_area= imagewindow_set_render_display();
+       
+       if(image_area) {
+               SpaceImage *sima= image_area->spacedata.first;
+               
+               areawinset(image_area->win);
+               
+               /* calc location using original size (tiles don't tell) */
+               sima->centx= (image_area->winx - sima->zoom*(float)rr->rectx)/2.0f;
+               sima->centy= (image_area->winy - sima->zoom*(float)rr->recty)/2.0f;
+               
+               sima->centx-= sima->zoom*sima->xof;
+               sima->centy-= sima->zoom*sima->yof;
+               
+               drawimagespace(image_area, sima);
+               if(image_area->headertype) scrarea_do_headdraw(image_area);
+               screen_swapbuffers();
+               
+               allqueue(REDRAWIMAGE, 0);       /* redraw in end */
+       }
+}
+
+/* coming from BIF_toggle_render_display() */
+void imagewindow_toggle_render(void)
+{
+       ScrArea *sa;
+       
+       /* check if any imagewindow is showing temporal render output */
+       for(sa=G.curscreen->areabase.first; sa; sa= sa->next) {
+               if(sa->spacetype==SPACE_IMAGE) {
+                       SpaceImage *sima= sa->spacedata.first;
+                       
+                       if(sima->image && strcmp(sima->image->name, "Render Result")==0 )
+                               if(sima->flag & (SI_PREVSPACE|SI_FULLWINDOW))
+                                       break;
+               }
+       }
+       if(sa) {
+               addqueue(sa->win, ESCKEY, 1);   /* also returns from fullscreen */
+       }
+       else {
+               sa= imagewindow_set_render_display();
+               scrarea_queue_headredraw(sa);
+               scrarea_queue_winredraw(sa);
+       }
+}
+
+static void imagewindow_renderinfo_cb(RenderStats *rs)
+{
+       
+       if(image_area) {
+               SpaceImage *sima= image_area->spacedata.first;
+               
+               if(sima->info_str==NULL)
+                       sima->info_str= MEM_callocN(RW_MAXTEXT, "info str imagewin");
+               
+               if(rs)
+                       make_renderinfo_string(rs, sima->info_str);
+
+               imagewindow_draw_renderinfo(image_area);
+               
+               image_area->win_swap= WIN_BACK_OK;
+               screen_swapbuffers();
+       }
+}
+
+
+void imagewindow_render_callbacks(Render *re)
+{
+       RE_display_init_cb(re, imagewindow_init_display_cb);
+       RE_display_draw_cb(re, imagewindow_progress_display_cb);
+       RE_display_clear_cb(re, imagewindow_clear_display_cb);
+       RE_stats_draw_cb(re, imagewindow_renderinfo_cb);        
+}
+
index a1891bd3182dc52edaf3e7be7093c39138ae4700..2af0e5de3d53e8fc5aa76d2308596bb09f5259e4 100644 (file)
@@ -180,8 +180,10 @@ static int choose_cursor(ScrArea *sa)
 void wich_cursor(ScrArea *sa)
 {
        sa->cursor= choose_cursor(sa);
-
-       screen_set_cursor(G.curscreen);
+       
+       /* well... the waitcursor() is not a state, so this call will cancel it out */
+       if(get_cursor()!=CURSOR_WAIT)
+               screen_set_cursor(G.curscreen);
 }
 
 
@@ -2215,7 +2217,12 @@ void setscreen(bScreen *sc)
        
        for(sa= sc->areabase.first; sa; sa= sa->next) {
                SpaceLink *sl;
-
+               
+               /* there's also events in queue for this, but we call fullscreen for render output
+                  now, and that doesn't go back to queue. Bad code, but doesn't hurt... (ton) */
+               scrarea_do_headchange(sa);
+               scrarea_do_winchange(sa);
+               
                for(sl= sa->spacedata.first; sl; sl= sl->next) {
                        sl->area= sa;
 
@@ -3673,7 +3680,7 @@ int get_cursor(void) {
 }
 
 void set_cursor(int curs) {
-       if (!(G.rendering) && G.background == 0) {
+       if (G.background == 0) {
                if (curs!=curcursor) {
                        curcursor= curs;
                        window_set_cursor(mainwin, curs);
index 324b3ba0cd45cb7a78c9c2390d58736ba1da0818..ede2b6d51d6a3579692d4ebe629f7bd2ae79ec2c 100644 (file)
@@ -407,13 +407,13 @@ static uiBlock *image_view_viewnavmenu(void *arg_unused)
 
        uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
 
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom 1:8", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom 1:4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom 1:2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom 1:1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom 2:1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom 4:1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom 8:1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom 1:8|Shift+NumPad 8", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom 1:4|Shift+NumPad 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom 1:2|Shift+NumPad 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom 1:1|NumPad 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom 2:1|NumPad 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom 4:1|NumPad 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom 8:1|NumPad 8", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, "");
 
        uiBlockSetDirection(block, UI_RIGHT);
        uiTextBoundsBlock(block, 50);
@@ -1198,17 +1198,17 @@ void image_buttons(void)
                uiDefIconButBitI(block, TOG, 1, B_SIMAPACKIMA, ICON_PACKAGE,    xco,0,XIC,YIC, &headerbuttons_packdummy, 0, 0, 0, 0, "Pack/Unpack this image");
                xco+= XIC+8;
 
-               uiDefIconButBitS(block, TOG, SI_DRAWTOOL, B_SIMAGEPAINTTOOL, ICON_TPAINT_HLT, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Enables painting textures on the image with left mouse button");
+               uiDefIconButBitI(block, TOG, SI_DRAWTOOL, B_SIMAGEPAINTTOOL, ICON_TPAINT_HLT, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Enables painting textures on the image with left mouse button");
                xco+= XIC+8;
 
                uiBlockBeginAlign(block);
-               uiDefIconButBitS(block, TOG, SI_USE_ALPHA, B_SIMA_USE_ALPHA, ICON_TRANSP_HLT, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Draws image with alpha");
+               uiDefIconButBitI(block, TOG, SI_USE_ALPHA, B_SIMA_USE_ALPHA, ICON_TRANSP_HLT, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Draws image with alpha");
                xco+= XIC;
-               uiDefIconButBitS(block, TOG, SI_SHOW_ALPHA, B_SIMA_SHOW_ALPHA, ICON_DOT, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Draws only alpha");
+               uiDefIconButBitI(block, TOG, SI_SHOW_ALPHA, B_SIMA_SHOW_ALPHA, ICON_DOT, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Draws only alpha");
                xco+= XIC;
                if(G.sima->image->ibuf) {
                        if(G.sima->image->ibuf->zbuf || G.sima->image->ibuf->zbuf_float) {
-                               uiDefIconButBitS(block, TOG, SI_SHOW_ZBUF, B_SIMA_SHOW_ZBUF, ICON_SOLID, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Draws zbuffer values");
+                               uiDefIconButBitI(block, TOG, SI_SHOW_ZBUF, B_SIMA_SHOW_ZBUF, ICON_SOLID, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Draws zbuffer values");
                                xco+= XIC;
                        }
                        else G.sima->flag &= ~SI_SHOW_ZBUF;     /* no confusing display for non-zbuf images */
index 4a93afd61370768d2b7e4e54e8a1a4bda06fdfc2..26a232f7a5da11a0f6880d8a36192c288dfa9f65 100644 (file)
@@ -73,6 +73,7 @@
 #include "BKE_utildefines.h"
 #include "BKE_writeavi.h"      /* movie handle */
 
+#include "BIF_drawimage.h"
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
 #include "BIF_graphics.h"
 /* forces draw of alpha */
 #define RW_FLAGS_ALPHA         (1<<4)
 
-/* space for info text */
-#define RW_HEADERY             18
-
-/* header print for window */
-#define RW_MAXTEXT             512
 
 typedef struct {
        Window *win;
@@ -889,38 +885,66 @@ static void renderwin_progress_display_cb(RenderResult *rr, volatile rcti *rect)
 
 /* -------------- callbacks for render loop: interactivity ----------------------- */
 
-
-/* callback for print info in top header of renderwin */
-static void printrenderinfo_cb(RenderStats *rs)
+/* string is RW_MAXTEXT chars min */
+void make_renderinfo_string(RenderStats *rs, char *str)
 {
        extern char info_time_str[32];  // header_info.c
        extern unsigned long mem_in_use, mmap_in_use;
        static float megs_used_memory, mmap_used_memory;
-       char *spos= render_win->render_text;
-               
+       char *spos= str;
+       
        megs_used_memory= (mem_in_use-mmap_in_use)/(1024.0*1024.0);
        mmap_used_memory= (mmap_in_use)/(1024.0*1024.0);
        
-       if(render_win) {
-               if(G.scene->lay & 0xFF000000)
-                       spos+= sprintf(spos, "Localview | ");
-               else if(G.scene->r.scemode & R_SINGLE_LAYER)
-                       spos+= sprintf(spos, "Single Layer | ");
+       if(G.scene->lay & 0xFF000000)
+               spos+= sprintf(spos, "Localview | ");
+       else if(G.scene->r.scemode & R_SINGLE_LAYER)
+               spos+= sprintf(spos, "Single Layer | ");
+       
+       if(rs->tothalo)
+               spos+= sprintf(spos, "Fra:%d  Ve:%d Fa:%d Ha:%d La:%d Mem:%.2fM (%.2fM)", (G.scene->r.cfra), rs->totvert, rs->totface, rs->tothalo, rs->totlamp, megs_used_memory, mmap_used_memory);
+       else 
+               spos+= sprintf(spos, "Fra:%d  Ve:%d Fa:%d La:%d Mem:%.2fM (%.2fM)", (G.scene->r.cfra), rs->totvert, rs->totface, rs->totlamp, megs_used_memory, mmap_used_memory);
+       
+       BLI_timestr(rs->lastframetime, info_time_str);
+       spos+= sprintf(spos, " Time:%s ", info_time_str);
+       
+       if(rs->infostr)
+               spos+= sprintf(spos, " | %s", rs->infostr);
+       
+       /* very weak... but 512 characters is quite safe... we cannot malloc during thread render */
+       if(spos >= str+RW_MAXTEXT)
+               printf("WARNING! renderwin text beyond limit \n");
+       
+       /* temporal render debug printing, needed for testing orange renders atm... will be gone soon (or option) */
+       if(G.rt==7 && rs->convertdone) {
+               char str[256];
                
-               if(rs->tothalo)
-                       spos+= sprintf(spos, "Fra:%d  Ve:%d Fa:%d Ha:%d La:%d Mem:%.2fM (%.2fM)", (G.scene->r.cfra), rs->totvert, rs->totface, rs->tothalo, rs->totlamp, megs_used_memory, mmap_used_memory);
-               else 
-                       spos+= sprintf(spos, "Fra:%d  Ve:%d Fa:%d La:%d Mem:%.2fM (%.2fM)", (G.scene->r.cfra), rs->totvert, rs->totface, rs->totlamp, megs_used_memory, mmap_used_memory);
-
-               BLI_timestr(rs->lastframetime, info_time_str);
-               spos+= sprintf(spos, " Time:%s ", info_time_str);
+               spos= str;
+               spos+= sprintf(spos, "Fra:%d Mem:%.2fM (%.2fM)", G.scene->r.cfra, megs_used_memory, mmap_used_memory);
                
-               if(rs->infostr)
+               if(rs->infostr) {
                        spos+= sprintf(spos, " | %s", rs->infostr);
+               }
+               else {
+                       if(rs->tothalo)
+                               spos+= sprintf(spos, "Sce: %s Ve:%d Fa:%d Ha:%d La:%d", G.scene->id.name+2, rs->totvert, rs->totface, rs->tothalo, rs->totlamp);
+                       else 
+                               spos+= sprintf(spos, "Sce: %s Ve:%d Fa:%d La:%d", G.scene->id.name+2, rs->totvert, rs->totface, rs->totlamp);
+               }
+               printf(str); printf("\n");
+       }       
+       
+       
+}
+
+/* callback for print info in top header of renderwin */
+static void renderwin_renderinfo_cb(RenderStats *rs)
+{
+       
+       if(render_win) {
                
-               /* very weak... but 512 characters is quite safe... we cannot malloc during thread render */
-               if(spos >= render_win->render_text+RW_MAXTEXT)
-                       printf("WARNING! renderwin text beyond limit \n");
+               make_renderinfo_string(rs, render_win->render_text);
                
 #ifdef __APPLE__
 #else
@@ -937,24 +961,6 @@ static void printrenderinfo_cb(RenderStats *rs)
 #endif
        }
 
-       /* temporal render debug printing, needed for testing orange renders atm... will be gone soon (or option) */
-       if(G.rt==7 && rs->convertdone) {
-               char str[256];
-               spos= str;
-               spos+= sprintf(spos, "Fra:%d Mem:%.2fM (%.2fM)", G.scene->r.cfra, megs_used_memory, mmap_used_memory);
-               
-               if(rs->infostr) {
-                       spos+= sprintf(spos, " | %s", rs->infostr);
-               }
-               else {
-                       if(rs->tothalo)
-                               spos+= sprintf(spos, "Sce: %s Ve:%d Fa:%d Ha:%d La:%d", G.scene->id.name+2, rs->totvert, rs->totface, rs->tothalo, rs->totlamp);
-                       else 
-                               spos+= sprintf(spos, "Sce: %s Ve:%d Fa:%d La:%d", G.scene->id.name+2, rs->totvert, rs->totface, rs->totlamp);
-               }
-               printf(str); printf("\n");
-       }       
-       
 }
 
 /* -------------- callback system to allow ESC from rendering ----------------------- */
@@ -1086,17 +1092,26 @@ static void do_render(int anim)
        G.afbreek= 0;
 
        /* set callbacks */
-       RE_display_init_cb(re, renderwin_init_display_cb);
-       RE_display_draw_cb(re, renderwin_progress_display_cb);
-       RE_display_clear_cb(re, renderwin_clear_display_cb);
+       if(G.displaymode!=R_DISPLAYWIN) {
+               if(render_win)
+                       BIF_close_render_display();
+               imagewindow_render_callbacks(re);
+       }
+       else {
+               RE_display_init_cb(re, renderwin_init_display_cb);
+               RE_display_draw_cb(re, renderwin_progress_display_cb);
+               RE_display_clear_cb(re, renderwin_clear_display_cb);
+               RE_stats_draw_cb(re, renderwin_renderinfo_cb);
+       }
        RE_error_cb(re, error_cb);
        init_test_break_callback();
        RE_test_break_cb(re, test_break);
        RE_timecursor_cb(re, set_timecursor);
-       RE_stats_draw_cb(re, printrenderinfo_cb);
        
-       if(render_win) window_set_cursor(render_win->win, CURSOR_WAIT);
-
+       waitcursor(1);
+       if(render_win) 
+               window_set_cursor(render_win->win, CURSOR_WAIT);
+       
        if(G.obedit)
                exit_editmode(0);       /* 0 = no free data */
 
@@ -1380,21 +1395,26 @@ void BIF_close_render_display(void)
 void BIF_toggle_render_display(void) 
 {
        
-       if (render_win) {
-               if(render_win->active) {
-                       mainwindow_raise();
-                       mainwindow_make_active();
-                       render_win->active= 0;
-               }
+       if (G.displaymode!=R_DISPLAYWIN) {
+               imagewindow_toggle_render();
+       }
+       else {
+               if (render_win) {
+                       if(render_win->active) {
+                               mainwindow_raise();
+                               mainwindow_make_active();
+                               render_win->active= 0;
+                       }
+                       else {
+                               window_raise(render_win->win);
+                               window_make_active(render_win->win);
+                               render_win->active= 1;
+                       }
+               } 
                else {
-                       window_raise(render_win->win);
-                       window_make_active(render_win->win);
-                       render_win->active= 1;
+                       RenderResult *rr= RE_GetResult(RE_GetRender(G.scene->id.name));
+                       if(rr) renderwin_init_display_cb(rr);
                }
-       } 
-       else {
-               RenderResult *rr= RE_GetResult(RE_GetRender(G.scene->id.name));
-               if(rr) renderwin_init_display_cb(rr);
        }
 }
 
index 515e8d212ff60a8b0e097bcdf4b6b3b0a9a7cfaf..871cb27f37e973c2a7acd48c85b846c6466dec9b 100644 (file)
@@ -4041,13 +4041,13 @@ static void changeimagepace(ScrArea *sa, void *spacedata)
 
 static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
 {
+       SpaceImage *sima= spacedata;
        unsigned short event= evt->event, origevent= evt->event;
        short val= evt->val;
-       SpaceImage *sima= curarea->spacedata.first;
        
        if(val==0) return;
 
-       if(uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
+       if(uiDoBlocks(&sa->uiblocks, event)!=UI_NOTHING ) event= 0;
        
        if (U.flag & USER_LMOUSESELECT) {
                if (event == LEFTMOUSE) {
@@ -4060,8 +4060,8 @@ static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
        if (sima->flag & SI_DRAWTOOL) {
                switch(event) {
                        case CKEY:
-                               toggle_blockhandler(curarea, IMAGE_HANDLER_PAINT, UI_PNL_UNSTOW);
-                               scrarea_queue_winredraw(curarea);
+                               toggle_blockhandler(sa, IMAGE_HANDLER_PAINT, UI_PNL_UNSTOW);
+                               scrarea_queue_winredraw(sa);
                                break;
                        case LEFTMOUSE:
                                imagepaint_paint(origevent==LEFTMOUSE? L_MOUSE: R_MOUSE);
@@ -4167,8 +4167,8 @@ static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                }
                                else {
                                        if(G.qual==LR_SHIFTKEY) {
-                                               toggle_blockhandler(curarea, IMAGE_HANDLER_PREVIEW, 0);
-                                               scrarea_queue_winredraw(curarea);
+                                               toggle_blockhandler(sa, IMAGE_HANDLER_PREVIEW, 0);
+                                               scrarea_queue_winredraw(sa);
                                        }
                                }
                                break;
@@ -4220,19 +4220,43 @@ static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                        image_viewmove(0);
                break;
        case WHEELUPMOUSE: case WHEELDOWNMOUSE: case PADPLUSKEY: case PADMINUS:
-               image_viewzoom(event, 0);
-               scrarea_queue_winredraw(curarea);
+       case PAD1: case PAD2: case PAD4: case PAD8:
+               image_viewzoom(event, (G.qual & LR_SHIFTKEY)==0);
+               scrarea_queue_winredraw(sa);
                break;
        case HOMEKEY:
                if((G.qual==0))
                        image_home();
+                       
                break;
        case NKEY:
                if(G.qual==0) {
-                       toggle_blockhandler(curarea, IMAGE_HANDLER_PROPERTIES, UI_PNL_TO_MOUSE);
-                       scrarea_queue_winredraw(curarea);
+                       toggle_blockhandler(sa, IMAGE_HANDLER_PROPERTIES, UI_PNL_TO_MOUSE);
+                       scrarea_queue_winredraw(sa);
                }
                break;
+       case ESCKEY:
+               if(sima->flag & SI_PREVSPACE) {
+                       /* only allow ESC once */
+                       sima->flag &= ~SI_PREVSPACE;
+                       
+                       sima= sa->spacedata.first;
+                       if(sima->next) {
+                               SpaceLink *sl;
+                               
+                               BLI_remlink(&sa->spacedata, sima);
+                               BLI_addtail(&sa->spacedata, sima);
+                               
+                               sl= sa->spacedata.first;
+                               
+                               newspace(sa, sl->spacetype);
+                       }
+               }
+               if(sima->flag & SI_FULLWINDOW) {
+                       sima->flag &= ~SI_FULLWINDOW;
+                       if(sa->full)
+                               area_fullscreen();
+               }
        }
 }
 
@@ -4869,6 +4893,8 @@ void freespacelist(ScrArea *sa)
                        SpaceImage *sima= (SpaceImage *)sl;
                        if(sima->cumap)
                                curvemapping_free(sima->cumap);
+                       if(sima->info_str)
+                               MEM_freeN(sima->info_str);
                }
                else if(sl->spacetype==SPACE_NODE) {
 /*                     SpaceNode *snode= (SpaceNode *)sl; */
@@ -4940,6 +4966,8 @@ void duplicatespacelist(ScrArea *newarea, ListBase *lb1, ListBase *lb2)
                        SpaceImage *sima= (SpaceImage *)sl;
                        if(sima->cumap)
                                sima->cumap= curvemapping_copy(sima->cumap);
+                       if(sima->info_str)
+                               sima->info_str= MEM_dupallocN(sima->info_str);
                }
                sl= sl->next;
        }