Threaded object update and EvaluationContext
[blender.git] / source / blender / windowmanager / intern / wm_playanim.c
index cc364c2a8387c32a4dc9c9b880eedd6abd97a340..ab48e72562ecf7e85a19d7cd9f3875635c550f25 100644 (file)
@@ -13,7 +13,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
@@ -60,6 +60,7 @@
 #include "IMB_imbuf.h"
 
 #include "BKE_blender.h"
+#include "BKE_depsgraph.h"
 #include "BKE_global.h"
 #include "BKE_image.h"
 
 #include "WM_api.h"  /* only for WM_main_playanim */
 
 struct PlayState;
-static void playanim_window_zoom(const struct PlayState *ps, const float zoom_offset);
+static void playanim_window_zoom(struct PlayState *ps, const float zoom_offset);
 
 typedef struct PlayState {
 
+       /* window and viewport size */
+       int win_x, win_y;
+       
+       /* current zoom level */
+       float zoom;
+
        /* playback state */
        short direction;
        short next_frame;
@@ -207,7 +214,6 @@ typedef struct PlayAnimPict {
 
 static struct ListBase picsbase = {NULL, NULL};
 static int fromdisk = FALSE;
-static float zoomx = 1.0, zoomy = 1.0;
 static double ptottime = 0.0, swaptime = 0.04;
 
 static PlayAnimPict *playanim_step(PlayAnimPict *playanim, int step)
@@ -237,8 +243,9 @@ static int pupdate_time(void)
        return (ptottime < 0);
 }
 
-static void playanim_toscreen(PlayAnimPict *picture, struct ImBuf *ibuf, int fontid, int fstep)
+static void playanim_toscreen(PlayState *ps, PlayAnimPict *picture, struct ImBuf *ibuf, int fontid, int fstep)
 {
+       float offsx, offsy;
 
        if (ibuf == NULL) {
                printf("%s: no ibuf for picture '%s'\n", __func__, picture ? picture->name : "<NIL>");
@@ -253,17 +260,29 @@ static void playanim_toscreen(PlayAnimPict *picture, struct ImBuf *ibuf, int fon
 
        GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);
 
-       glRasterPos2f(0.0f, 0.0f);
+       /* offset within window */
+       offsx = 0.5f * (((float)ps->win_x - ps->zoom * ibuf->x) / (float)ps->win_x);
+       offsy = 0.5f * (((float)ps->win_y - ps->zoom * ibuf->y) / (float)ps->win_y);
 
-       glEnable(GL_BLEND);
-       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       CLAMP(offsx, 0.0f, 1.0f);
+       CLAMP(offsy, 0.0f, 1.0f);
+       glRasterPos2f(offsx, offsy);
 
-       fdrawcheckerboard(0.0f, 0.0f, ibuf->x, ibuf->y);
+       glClearColor(0.1, 0.1, 0.1, 0.0);
+       glClear(GL_COLOR_BUFFER_BIT);
+       
+       /* checkerboard for case alpha */
+       if (ibuf->planes == 32) {
+               glEnable(GL_BLEND);
+               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
+               fdrawcheckerboard(offsx, offsy, offsx + (ps->zoom * ibuf->x) / (float)ps->win_x, offsy + (ps->zoom * ibuf->y) / (float)ps->win_y);
+       }
+       
        glDrawPixels(ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
 
        glDisable(GL_BLEND);
-
+       
        pupdate_time();
 
        if (picture && (g_WS.qual & (WS_QUAL_SHIFT | WS_QUAL_LMOUSE)) && (fontid != -1)) {
@@ -286,7 +305,7 @@ static void playanim_toscreen(PlayAnimPict *picture, struct ImBuf *ibuf, int fon
        GHOST_SwapWindowBuffers(g_WS.ghost_window);
 }
 
-static void build_pict_list(char *first, int totframes, int fstep, int fontid)
+static void build_pict_list(PlayState *ps, char *first, int totframes, int fstep, int fontid)
 {
        char *mem, filepath[FILE_MAX];
 //     short val;
@@ -302,7 +321,7 @@ static void build_pict_list(char *first, int totframes, int fstep, int fontid)
                        int pic;
                        ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
                        if (ibuf) {
-                               playanim_toscreen(NULL, ibuf, fontid, fstep);
+                               playanim_toscreen(ps, NULL, ibuf, fontid, fstep);
                                IMB_freeImBuf(ibuf);
                        }
 
@@ -405,7 +424,7 @@ static void build_pict_list(char *first, int totframes, int fstep, int fontid)
                                        ibuf = IMB_loadiffname(picture->name, picture->IB_flags, NULL);
                                }
                                if (ibuf) {
-                                       playanim_toscreen(picture, ibuf, fontid, fstep);
+                                       playanim_toscreen(ps, picture, ibuf, fontid, fstep);
                                        IMB_freeImBuf(ibuf);
                                }
                                pupdate_time();
@@ -709,28 +728,33 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
                case GHOST_kEventWindowSize:
                case GHOST_kEventWindowMove:
                {
-                       int sizex, sizey;
-
-                       playanim_window_get_size(&sizex, &sizey);
+                       float zoomx, zoomy;
+                       
+                       playanim_window_get_size(&ps->win_x, &ps->win_y);
                        GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);
 
-                       glViewport(0, 0, sizex, sizey);
-                       glScissor(0, 0, sizex, sizey);
-
-                       zoomx = (float) sizex / ps->ibufx;
-                       zoomy = (float) sizey / ps->ibufy;
-                       zoomx = floor(zoomx + 0.5f);
-                       zoomy = floor(zoomy + 0.5f);
-                       if (zoomx < 1.0f) zoomx = 1.0f;
-                       if (zoomy < 1.0f) zoomy = 1.0f;
-
-                       sizex = zoomx * ps->ibufx;
-                       sizey = zoomy * ps->ibufy;
+                       zoomx = (float) ps->win_x / ps->ibufx;
+                       zoomy = (float) ps->win_y / ps->ibufy;
+                       
+                       /* zoom always show entire image */
+                       ps->zoom = MIN2(zoomx, zoomy);
+                       
+                       /* zoom steps of 2 for speed */
+                       ps->zoom = floor(ps->zoom + 0.5f);
+                       if (ps->zoom < 1.0f) ps->zoom = 1.0f;
+                       
+                       glViewport(0, 0, ps->win_x, ps->win_y);
+                       glScissor(0, 0, ps->win_x, ps->win_y);
+                       
+                       /* unified matrix, note it affects offset for drawing */
+                       glMatrixMode(GL_PROJECTION);
+                       glLoadIdentity();
+                       glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
+                       glMatrixMode(GL_MODELVIEW);
 
-                       glPixelZoom(zoomx, zoomy);
-                       glEnable(GL_DITHER);
+                       glPixelZoom(ps->zoom, ps->zoom);
                        ptottime = 0.0;
-                       playanim_toscreen(ps->picture, ps->curframe_ibuf, ps->fontid, ps->fstep);
+                       playanim_toscreen(ps, ps->picture, ps->curframe_ibuf, ps->fontid, ps->fstep);
 
                        break;
                }
@@ -765,45 +789,39 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
        return 1;
 }
 
-static void playanim_window_open(const char *title, int posx, int posy, int sizex, int sizey, int start_maximized)
+static void playanim_window_open(const char *title, int posx, int posy, int sizex, int sizey)
 {
-       GHOST_TWindowState inital_state;
        GHOST_TUns32 scr_w, scr_h;
 
        GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &scr_w, &scr_h);
 
        posy = (scr_h - posy - sizey);
 
-       if (start_maximized == G_WINDOWSTATE_FULLSCREEN)
-               inital_state = start_maximized ? GHOST_kWindowStateFullScreen : GHOST_kWindowStateNormal;
-       else
-               inital_state = start_maximized ? GHOST_kWindowStateMaximized : GHOST_kWindowStateNormal;
-
        g_WS.ghost_window = GHOST_CreateWindow(g_WS.ghost_system,
                                               title,
                                               posx, posy, sizex, sizey,
-                                              inital_state,
+                                              /* could optionally start fullscreen */
+                                              GHOST_kWindowStateNormal,
                                               GHOST_kDrawingContextTypeOpenGL,
                                               FALSE /* no stereo */, FALSE);
 }
 
-static void playanim_window_zoom(const PlayState *ps, const float zoom_offset)
+static void playanim_window_zoom(PlayState *ps, const float zoom_offset)
 {
        int sizex, sizey;
        /* int ofsx, ofsy; */ /* UNUSED */
 
-       if (zoomx + zoom_offset > 0.0f) zoomx += zoom_offset;
-       if (zoomy + zoom_offset > 0.0f) zoomy += zoom_offset;
+       if (ps->zoom + zoom_offset > 0.0f) ps->zoom += zoom_offset;
 
        // playanim_window_get_position(&ofsx, &ofsy);
        playanim_window_get_size(&sizex, &sizey);
        /* ofsx += sizex / 2; */ /* UNUSED */
        /* ofsy += sizey / 2; */ /* UNUSED */
-       sizex = zoomx * ps->ibufx;
-       sizey = zoomy * ps->ibufy;
+       sizex = ps->zoom * ps->ibufx;
+       sizey = ps->zoom * ps->ibufy;
        /* ofsx -= sizex / 2; */ /* UNUSED */
        /* ofsy -= sizey / 2; */ /* UNUSED */
-       // window_set_position(g_WS.ghost_window,sizex,sizey);
+       // window_set_position(g_WS.ghost_window, sizex, sizey);
        GHOST_SetClientSize(g_WS.ghost_window, sizex, sizey);
 }
 
@@ -836,6 +854,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
        ps.stopped   = FALSE;
        ps.picture   = NULL;
        ps.dropped_file[0] = 0;
+       ps.zoom      = 1.0f;
        /* resetmap = FALSE */
 
        ps.fstep     = 1;
@@ -877,17 +896,20 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
                                        }
                                        break;
                                case 's':
-                                       sfra = MIN2(MAXFRAME, MAX2(1, atoi(argv[2]) ));
+                                       sfra = atoi(argv[2]);
+                                       CLAMP(sfra, 1, MAXFRAME);
                                        argc--;
                                        argv++;
                                        break;
                                case 'e':
-                                       efra = MIN2(MAXFRAME, MAX2(1, atoi(argv[2]) ));
+                                       efra = atoi(argv[2]);
+                                       CLAMP(efra, 1, MAXFRAME);
                                        argc--;
                                        argv++;
                                        break;
                                case 'j':
-                                       ps.fstep = MIN2(MAXFRAME, MAX2(1, atoi(argv[2])));
+                                       ps.fstep = atoi(argv[2]);
+                                       CLAMP(ps.fstep, 1, MAXFRAME);
                                        swaptime *= ps.fstep;
                                        argc--;
                                        argv++;
@@ -922,6 +944,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
                }
        }
        else if (!IMB_ispic(filepath)) {
+               printf("%s: '%s' not an image file\n", __func__, filepath);
                exit(1);
        }
 
@@ -931,30 +954,26 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
        }
 
        if (ibuf == NULL) {
-               printf("couldn't open %s\n", filepath);
+               printf("%s: '%s' couldn't open\n", __func__, filepath);
                exit(1);
        }
 
 #if 0 //XXX25
-       #if !defined(WIN32) && !defined(__APPLE__)
+#if !defined(WIN32) && !defined(__APPLE__)
        if (fork()) exit(0);
-       #endif
+#endif
 #endif //XXX25
 
-       /* XXX, fixme zr */
        {
-//             extern void add_to_mainqueue(wmWindow *win, void *user_data, short evt, short val, char ascii);
 
                GHOST_EventConsumerHandle consumer = GHOST_CreateEventConsumer(ghost_event_proc, &ps);
 
                g_WS.ghost_system = GHOST_CreateSystem();
                GHOST_AddEventConsumer(g_WS.ghost_system, consumer);
 
+               playanim_window_open("Blender:Anim", start_x, start_y, ibuf->x, ibuf->y);
 
-
-               playanim_window_open("Blender:Anim", start_x, start_y, ibuf->x, ibuf->y, 0);
-//XXX25                window_set_handler(g_WS.ghost_window, add_to_mainqueue, NULL);
-
+               /* unified matrix, note it affects offset for drawing */
                glMatrixMode(GL_PROJECTION);
                glLoadIdentity();
                glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
@@ -972,11 +991,15 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
 
        ps.ibufx = ibuf->x;
        ps.ibufy = ibuf->y;
+       
+       ps.win_x = ps.ibufx;
+       ps.win_y = ps.ibufy;
 
        if (maxwinx % ibuf->x) maxwinx = ibuf->x * (1 + (maxwinx / ibuf->x));
        if (maxwiny % ibuf->y) maxwiny = ibuf->y * (1 + (maxwiny / ibuf->y));
 
-       glClearColor(0.0, 0.0, 0.0, 0.0);
+       
+       glClearColor(0.1, 0.1, 0.1, 0.0);
        glClear(GL_COLOR_BUFFER_BIT);
 
        GHOST_SwapWindowBuffers(g_WS.ghost_window);
@@ -987,11 +1010,11 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
                efra = MAXFRAME;
        }
 
-       build_pict_list(filepath, (efra - sfra) + 1, ps.fstep, ps.fontid);
+       build_pict_list(&ps, filepath, (efra - sfra) + 1, ps.fstep, ps.fontid);
 
        for (i = 2; i < argc; i++) {
                BLI_strncpy(filepath, argv[i], sizeof(filepath));
-               build_pict_list(filepath, (efra - sfra) + 1, ps.fstep, ps.fontid);
+               build_pict_list(&ps, filepath, (efra - sfra) + 1, ps.fstep, ps.fontid);
        }
 
        IMB_freeImBuf(ibuf);
@@ -1064,8 +1087,8 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
 
                                while (pupdate_time()) PIL_sleep_ms(1);
                                ptottime -= swaptime;
-                               playanim_toscreen(ps.picture, ibuf, ps.fontid, ps.fstep);
-                       } /* else deleten */
+                               playanim_toscreen(&ps, ps.picture, ibuf, ps.fontid, ps.fstep);
+                       } /* else delete */
                        else {
                                printf("error: can't play this image type\n");
                                exit(0);
@@ -1083,16 +1106,17 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
                        ps.next_frame = ps.direction;
 
 
-                       while ((hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0) || ps.wait2 != 0)) {
+                       while ( (hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0)) || ps.wait2 != 0) {
                                if (hasevent) {
                                        GHOST_DispatchEvents(g_WS.ghost_system);
                                }
+                               /* Note, this still draws for mousemoves on pause */
                                if (ps.wait2) {
                                        if (hasevent) {
                                                if (ibuf) {
                                                        while (pupdate_time()) PIL_sleep_ms(1);
                                                        ptottime -= swaptime;
-                                                       playanim_toscreen(ps.picture, ibuf, ps.fontid, ps.fstep);
+                                                       playanim_toscreen(&ps, ps.picture, ibuf, ps.fontid, ps.fstep);
                                                }
                                        }
                                }
@@ -1171,13 +1195,14 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
        GHOST_DisposeWindow(g_WS.ghost_system, g_WS.ghost_window);
 
        /* early exit, IMB and BKE should be exited only in end */
-       if (ps.dropped_file) {
+       if (ps.dropped_file[0]) {
                BLI_strncpy(filepath, ps.dropped_file, sizeof(filepath));
                return filepath;
        }
        
        IMB_exit();
        BKE_images_exit();
+       DAG_exit();
 
        totblock = MEM_get_memory_blocks_in_use();
        if (totblock != 0) {