bring back the play option from 2.4x
authorCampbell Barton <ideasman42@gmail.com>
Mon, 6 Aug 2012 16:07:11 +0000 (16:07 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Mon, 6 Aug 2012 16:07:11 +0000 (16:07 +0000)
release/scripts/startup/bl_operators/screen_play_rendered_anim.py
release/scripts/startup/bl_ui/properties_render.py
source/blender/editors/interface/resources.c
source/blender/makesrna/intern/rna_userdef.c
source/blender/windowmanager/CMakeLists.txt
source/blender/windowmanager/intern/wm_playanim.c [new file with mode: 0644]
source/creator/creator.c

index 9cb9dfc708c270bf4bcc50be435ad499e91e23a4..b4733ac9d87716d31d8d36990a14a2ef64267f32 100644 (file)
@@ -28,7 +28,9 @@ import os
 def guess_player_path(preset):
     import sys
 
-    if preset == 'BLENDER24':
+    if preset == 'INTERNAL':
+        return bpy.app.binary_path
+    elif preset == 'BLENDER24':
         player_path = "blender"
 
         if sys.platform == "darwin":
@@ -110,32 +112,7 @@ class PlayRenderedAnim(Operator):
 
         cmd = [player_path]
         # extra options, fps controls etc.
-        if preset == 'BLENDER24':
-            # -----------------------------------------------------------------
-            # Check blender is not 2.5x until it supports playback again
-            try:
-                process = subprocess.Popen([player_path, '--version'],
-                                           stdout=subprocess.PIPE,
-                                           )
-            except:
-                # ignore and allow the main execution to catch the problem.
-                process = None
-
-            if process is not None:
-                process.wait()
-                out = process.stdout.read()
-                process.stdout.close()
-                out_split = out.strip().split()
-                if out_split[0] == b'Blender':
-                    if not out_split[1].startswith(b'2.4'):
-                        self.report({'ERROR'},
-                                    "Blender %s doesn't support playback: %r" %
-                                    (out_split[1].decode(), player_path))
-                        return {'CANCELLED'}
-                del out, out_split
-            del process
-            # -----------------------------------------------------------------
-
+        if preset in {'BLENDER24', 'INTERNAL'}:
             opts = ["-a", "-f", str(rd.fps), str(rd.fps_base),
                     "-j", str(scene.frame_step), file]
             cmd.extend(opts)
index 1ed3638080a199d40e58eb31be53a57392e61a06..74bb720b6189605ded8268130a4900e9ed5b2073 100644 (file)
@@ -66,6 +66,7 @@ class RENDER_PT_render(RenderButtonsPanel, Panel):
         row = layout.row()
         row.operator("render.render", text="Image", icon='RENDER_STILL')
         row.operator("render.render", text="Animation", icon='RENDER_ANIMATION').animation = True
+        row.operator("render.play_rendered_anim", text="Play", icon='RENDER_ANIMATION')
 
         layout.prop(rd, "display_mode", text="Display")
 
index 9489e6b54408f87a3d815ef67ea562e38b11be3f..0ff81f27f6b977e470e631cb3fb403828d5c35ce 100644 (file)
@@ -1950,9 +1950,6 @@ void init_userdef_do_versions(void)
        if (U.dbl_click_time == 0) {
                U.dbl_click_time = 350;
        }
-       if (U.anim_player_preset == 0) {
-               U.anim_player_preset = 1;
-       }
        if (U.scrcastfps == 0) {
                U.scrcastfps = 10;
                U.scrcastwait = 50;
index 5820de3a7e2aee2453bc31620fbc3f6fc4ddc37e..03fd144f7dd47c591451d7f2cfa880514830da68 100644 (file)
@@ -3450,7 +3450,7 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna)
        StructRNA *srna;
        
        static EnumPropertyItem anim_player_presets[] = {
-               /*{0, "INTERNAL", 0, "Internal", "Built-in animation player"},   *//* doesn't work yet! */
+               {0, "INTERNAL", 0, "Internal", "Built-in animation player"}, /* doesn't work yet! */
                {1, "BLENDER24", 0, "Blender 2.4", "Blender command line animation playback - path to Blender 2.4"},
                {2, "DJV", 0, "Djv", "Open source frame player: http://djv.sourceforge.net"},
                {3, "FRAMECYCLER", 0, "FrameCycler", "Frame player from IRIDAS"},
index c5aaeeb81714fc495dc5ea90ceb800cab8929d40..f44ec2f5dc8b0fbd255ff455328c2b52c9297369 100644 (file)
@@ -53,6 +53,7 @@ set(INC_SYS
 
 set(SRC
        intern/wm.c
+       intern/wm_playanim.c
        intern/wm_cursors.c
        intern/wm_dragdrop.c
        intern/wm_draw.c
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
new file mode 100644 (file)
index 0000000..3c791cb
--- /dev/null
@@ -0,0 +1,1136 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/intern/wm_playanim.c
+ *  \ingroup wm
+ *
+ * \note This file uses ghost directly and none of the WM definitions.
+ *       this could be made into its own module, alongside creator/
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#ifndef WIN32
+#  include <unistd.h>
+#  include <sys/times.h>
+#  include <sys/wait.h>
+#else
+#  include <io.h>
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "PIL_time.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_path_util.h"
+#include "BLI_fileops.h"
+#include "BLI_rect.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "BKE_blender.h"
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#ifdef WITH_QUICKTIME
+#  ifdef _WIN32
+#    include <QTML.h>
+#    include <Movies.h>
+#  elif defined(__APPLE__)
+#    include <QuickTime/Movies.h>
+#  endif /* __APPLE__ */
+#endif /* WITH_QUICKTIME */
+
+#include "DNA_scene_types.h"
+#include "BLI_utildefines.h"
+#include "ED_datafiles.h" /* for fonts */
+#include "wm_event_types.h"
+#include "GHOST_C-api.h"
+#include "BLF_api.h"
+
+
+typedef struct PlayState {
+
+       /* playback state */
+       short direction;
+       short next;
+       short once;
+       short turbo;
+       short pingpong;
+       short noskip;
+       short sstep;
+       short pause;
+       short wait2;
+       short stopped;
+       short go;
+
+       /* current picture */
+       struct PlayAnimPict *picture;
+
+       /* set once at the start */
+       int ibufx, ibufy;
+       int fontid;
+
+       /* saves passing args */
+       struct ImBuf *curframe_ibuf;
+} PlayState;
+
+/* for debugging */
+#if 0
+void print_ps(PlayState *ps)
+{
+       printf("ps:\n");
+       printf("    direction=%d,\n", (int)ps->direction);
+       printf("    next=%d,\n", ps->next);
+       printf("    once=%d,\n", ps->once);
+       printf("    turbo=%d,\n", ps->turbo);
+       printf("    pingpong=%d,\n", ps->pingpong);
+       printf("    noskip=%d,\n", ps->noskip);
+       printf("    sstep=%d,\n", ps->sstep);
+       printf("    pause=%d,\n", ps->pause);
+       printf("    wait2=%d,\n", ps->wait2);
+       printf("    stopped=%d,\n", ps->stopped);
+       printf("    go=%d,\n\n", ps->go);
+       fflush(stdout);
+}
+#endif
+
+/* global for window and events */
+typedef enum eWS_Qual {
+       WS_QUAL_LSHIFT  = (1 << 0),
+       WS_QUAL_RSHIFT  = (1 << 1),
+       WS_QUAL_SHIFT   = (WS_QUAL_LSHIFT | WS_QUAL_RSHIFT),
+       WS_QUAL_LALT    = (1 << 2),
+       WS_QUAL_RALT    = (1 << 3),
+       WS_QUAL_ALT     = (WS_QUAL_LALT | WS_QUAL_RALT),
+       WS_QUAL_LCTRL   = (1 << 4),
+       WS_QUAL_RCTRL   = (1 << 5),
+       WS_QUAL_LMOUSE  = (1 << 16),
+       WS_QUAL_MMOUSE  = (1 << 17),
+       WS_QUAL_RMOUSE  = (1 << 18),
+       WS_QUAL_MOUSE   = (WS_QUAL_LMOUSE | WS_QUAL_MMOUSE | WS_QUAL_RMOUSE)
+} eWS_Qual;
+
+static struct WindowStateGlobal {
+       GHOST_SystemHandle ghost_system;
+       void *ghost_window;
+
+       /* events */
+       eWS_Qual qual;
+} g_WS = {NULL};
+
+void playanim_window_get_size(int *width_r, int *height_r)
+{
+       GHOST_RectangleHandle bounds = GHOST_GetClientBounds(g_WS.ghost_window);
+       *width_r = GHOST_GetWidthRectangle(bounds);
+       *height_r = GHOST_GetHeightRectangle(bounds);
+       GHOST_DisposeRectangle(bounds);
+}
+
+/* implementation */
+static void playanim_event_qual_update(void)
+{
+       int val;
+
+       /* Shift */
+       GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyLeftShift, &val);
+       if (val) g_WS.qual |=  WS_QUAL_LSHIFT;
+       else     g_WS.qual &= ~WS_QUAL_LSHIFT;
+
+       GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyRightShift, &val);
+       if (val) g_WS.qual |=  WS_QUAL_RSHIFT;
+       else     g_WS.qual &= ~WS_QUAL_RSHIFT;
+
+       /* Control */
+       GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyLeftControl, &val);
+       if (val) g_WS.qual |=  WS_QUAL_LCTRL;
+       else     g_WS.qual &= ~WS_QUAL_LCTRL;
+
+       GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyRightControl, &val);
+       if (val) g_WS.qual |=  WS_QUAL_RCTRL;
+       else     g_WS.qual &= ~WS_QUAL_RCTRL;
+
+       /* Alt */
+       GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyLeftAlt, &val);
+       if (val) g_WS.qual |=  WS_QUAL_LCTRL;
+       else     g_WS.qual &= ~WS_QUAL_LCTRL;
+
+       GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyRightAlt, &val);
+       if (val) g_WS.qual |=  WS_QUAL_RCTRL;
+       else     g_WS.qual &= ~WS_QUAL_RCTRL;
+
+       /* LMB */
+       GHOST_GetButtonState(g_WS.ghost_system, GHOST_kButtonMaskLeft, &val);
+       if (val) g_WS.qual |=  WS_QUAL_LMOUSE;
+       else     g_WS.qual &= ~WS_QUAL_LMOUSE;
+
+       /* MMB */
+       GHOST_GetButtonState(g_WS.ghost_system, GHOST_kButtonMaskMiddle, &val);
+       if (val) g_WS.qual |=  WS_QUAL_MMOUSE;
+       else     g_WS.qual &= ~WS_QUAL_MMOUSE;
+
+       /* RMB */
+       GHOST_GetButtonState(g_WS.ghost_system, GHOST_kButtonMaskRight, &val);
+       if (val) g_WS.qual |=  WS_QUAL_RMOUSE;
+       else     g_WS.qual &= ~WS_QUAL_RMOUSE;
+}
+
+typedef struct PlayAnimPict {
+       struct PlayAnimPict *next, *prev;
+       char *mem;
+       int size;
+       char *name;
+       struct ImBuf *ibuf;
+       struct anim *anim;
+       int frame;
+       int IB_flags;
+} PlayAnimPict;
+
+static struct ListBase picsbase = {NULL, NULL};
+static int fromdisk = FALSE;
+static int fstep = 1;
+static float zoomx = 1.0, zoomy = 1.0;
+static double ptottime = 0.0, swaptime = 0.04;
+
+static int pupdate_time(void)
+{
+       static double ltime;
+       double time;
+
+       time = PIL_check_seconds_timer();
+
+       ptottime += (time - ltime);
+       ltime = time;
+       return (ptottime < 0);
+}
+
+static void playanim_toscreen(PlayAnimPict *picture, struct ImBuf *ibuf, int fontid)
+{
+
+       if (ibuf == NULL) {
+               printf("no ibuf !\n");
+               return;
+       }
+       if (ibuf->rect == NULL && ibuf->rect_float) {
+               IMB_rect_from_float(ibuf);
+               imb_freerectfloatImBuf(ibuf);
+       }
+       if (ibuf->rect == NULL)
+               return;
+
+       GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);
+
+       glRasterPos2f(0.0f, 0.0f);
+
+       glDrawPixels(ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+
+       pupdate_time();
+
+       if (picture && (g_WS.qual & (WS_QUAL_SHIFT | WS_QUAL_LMOUSE)) && (fontid != -1)) {
+               int sizex, sizey;
+               float fsizex_inv, fsizey_inv;
+               char str[32 + FILE_MAX];
+               cpack(-1);
+               BLI_snprintf(str, sizeof(str), "%s | %.2f frames/s", picture->name, fstep / swaptime);
+
+               playanim_window_get_size(&sizex, &sizey);
+               fsizex_inv = 1.0f / sizex;
+               fsizey_inv = 1.0f / sizey;
+
+               BLF_enable(fontid, BLF_ASPECT);
+               BLF_aspect(fontid, fsizex_inv, fsizey_inv, 1.0f);
+               BLF_position(fontid, 10.0f * fsizex_inv, 10.0f * fsizey_inv, 0.0f);
+               BLF_draw(fontid, str, sizeof(str));
+       }
+
+       GHOST_SwapWindowBuffers(g_WS.ghost_window);
+}
+
+static void build_pict_list(char *first, int totframes, int fstep, int fontid)
+{
+       char *mem, filepath[FILE_MAX];
+//     short val;
+       PlayAnimPict *picture = NULL;
+       struct ImBuf *ibuf = NULL;
+       char str[32 + FILE_MAX];
+       struct anim *anim;
+
+       if (IMB_isanim(first)) {
+               anim = IMB_open_anim(first, IB_rect, 0);
+               if (anim) {
+                       int pic;
+                       ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
+                       if (ibuf) {
+                               playanim_toscreen(NULL, ibuf, fontid);
+                               IMB_freeImBuf(ibuf);
+                       }
+
+                       for (pic = 0; pic < IMB_anim_get_duration(anim, IMB_TC_NONE); pic++) {
+                               picture = (PlayAnimPict *)MEM_callocN(sizeof(PlayAnimPict), "Pict");
+                               picture->anim = anim;
+                               picture->frame = pic;
+                               picture->IB_flags = IB_rect;
+                               BLI_snprintf(str, sizeof(str), "%s : %4.d", first, pic + 1);
+                               picture->name = strdup(str);
+                               BLI_addtail(&picsbase, picture);
+                       }
+               }
+               else {
+                       printf("couldn't open anim %s\n", first);
+               }
+       }
+       else {
+               int count = 0;
+
+               BLI_strncpy(filepath, first, sizeof(filepath));
+
+               pupdate_time();
+               ptottime = 1.0;
+
+               /* O_DIRECT
+                *
+                * If set, all reads and writes on the resulting file descriptor will
+                * be performed directly to or from the user program buffer, provided
+                * appropriate size and alignment restrictions are met.  Refer to the
+                * F_SETFL and F_DIOINFO commands in the fcntl(2) manual entry for
+                * information about how to determine the alignment constraints.
+                * O_DIRECT is a Silicon Graphics extension and is only supported on
+                * local EFS and XFS file systems.
+                */
+
+               while (IMB_ispic(filepath) && totframes) {
+                       size_t size;
+                       int file;
+
+                       file = open(filepath, O_BINARY | O_RDONLY, 0);
+                       if (file < 0) return;
+                       picture = (PlayAnimPict *)MEM_callocN(sizeof(PlayAnimPict), "picture");
+                       if (picture == NULL) {
+                               printf("Not enough memory for pict struct '%s'\n", filepath);
+                               close(file);
+                               return;
+                       }
+                       size = BLI_file_descriptor_size(file);
+
+                       if (size < 1) {
+                               close(file);
+                               MEM_freeN(picture);
+                               return;
+                       }
+
+                       picture->size = size;
+                       picture->IB_flags = IB_rect;
+
+                       if (fromdisk == FALSE) {
+                               mem = (char *)MEM_mallocN(size, "build pic list");
+                               if (mem == NULL) {
+                                       printf("Couldn't get memory\n");
+                                       close(file);
+                                       MEM_freeN(picture);
+                                       return;
+                               }
+
+                               if (read(file, mem, size) != size) {
+                                       printf("Error while reading %s\n", filepath);
+                                       close(file);
+                                       MEM_freeN(picture);
+                                       MEM_freeN(mem);
+                                       return;
+                               }
+                       }
+                       else {
+                               mem = NULL;
+                       }
+
+                       picture->mem = mem;
+                       picture->name = strdup(filepath);
+                       close(file);
+                       BLI_addtail(&picsbase, picture);
+                       count++;
+
+                       pupdate_time();
+
+                       if (ptottime > 1.0) {
+                               if (picture->mem) {
+                                       ibuf = IMB_ibImageFromMemory((unsigned char *)picture->mem, picture->size,
+                                                                    picture->IB_flags, picture->name);
+                               }
+                               else {
+                                       ibuf = IMB_loadiffname(picture->name, picture->IB_flags);
+                               }
+                               if (ibuf) {
+                                       playanim_toscreen(picture, ibuf, fontid);
+                                       IMB_freeImBuf(ibuf);
+                               }
+                               pupdate_time();
+                               ptottime = 0.0;
+                       }
+
+                       BLI_newname(filepath, +fstep);
+
+#if 0 // XXX25
+                       while (qtest()) {
+                               switch (qreadN(&val)) {
+                                       case ESCKEY:
+                                               if (val) return;
+                                               break;
+                               }
+                       }
+#endif
+                       totframes--;
+               }
+       }
+       return;
+}
+
+static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
+{
+       PlayState *ps = (PlayState *)ps_void;
+       GHOST_TEventType type = GHOST_GetEventType(evt);
+       int val;
+
+       // print_ps(ps);
+
+       playanim_event_qual_update();
+
+       /* convert ghost event into value keyboard or mouse */
+       val = ELEM(type, GHOST_kEventKeyDown, GHOST_kEventButtonDown);
+
+       if (ps->wait2 && ps->stopped) {
+               ps->stopped = FALSE;
+       }
+
+       switch (type) {
+               case GHOST_kEventKeyDown:
+               case GHOST_kEventKeyUp:
+               {
+                       GHOST_TEventKeyData *key_data;
+
+                       key_data = (GHOST_TEventKeyData *)GHOST_GetEventData(evt);
+                       switch (key_data->key) {
+                               case GHOST_kKeyA:
+                                       if (val) ps->noskip = !ps->noskip;
+                                       break;
+                               case GHOST_kKeyP:
+                                       if (val) ps->pingpong = !ps->pingpong;
+                                       break;
+                               case GHOST_kKeyNumpad1:
+                                       if (val) swaptime = fstep / 60.0;
+                                       break;
+                               case GHOST_kKeyNumpad2:
+                                       if (val) swaptime = fstep / 50.0;
+                                       break;
+                               case GHOST_kKeyNumpad3:
+                                       if (val) swaptime = fstep / 30.0;
+                                       break;
+                               case GHOST_kKeyNumpad4:
+                                       if (g_WS.qual & WS_QUAL_SHIFT)
+                                               swaptime = fstep / 24.0;
+                                       else
+                                               swaptime = fstep / 25.0;
+                                       break;
+                               case GHOST_kKeyNumpad5:
+                                       if (val) swaptime = fstep / 20.0;
+                                       break;
+                               case GHOST_kKeyNumpad6:
+                                       if (val) swaptime = fstep / 15.0;
+                                       break;
+                               case GHOST_kKeyNumpad7:
+                                       if (val) swaptime = fstep / 12.0;
+                                       break;
+                               case GHOST_kKeyNumpad8:
+                                       if (val) swaptime = fstep / 10.0;
+                                       break;
+                               case GHOST_kKeyNumpad9:
+                                       if (val) swaptime = fstep / 6.0;
+                                       break;
+                               case GHOST_kKeyLeftArrow:
+                                       if (val) {
+                                               ps->sstep = TRUE;
+                                               ps->wait2 = FALSE;
+                                               if (g_WS.qual & WS_QUAL_SHIFT) {
+                                                       ps->picture = picsbase.first;
+                                                       ps->next = 0;
+                                               }
+                                               else {
+                                                       ps->next = -1;
+                                               }
+                                       }
+                                       break;
+                               case GHOST_kKeyDownArrow:
+                                       if (val) {
+                                               ps->wait2 = FALSE;
+                                               if (g_WS.qual & WS_QUAL_SHIFT) {
+                                                       ps->next = ps->direction = -1;
+                                               }
+                                               else {
+                                                       ps->next = -10;
+                                                       ps->sstep = TRUE;
+                                               }
+                                       }
+                                       break;
+                               case GHOST_kKeyRightArrow:
+                                       if (val) {
+                                               ps->sstep = TRUE;
+                                               ps->wait2 = FALSE;
+                                               if (g_WS.qual & WS_QUAL_SHIFT) {
+                                                       ps->picture = picsbase.last;
+                                                       ps->next = 0;
+                                               }
+                                               else {
+                                                       ps->next = 1;
+                                               }
+                                       }
+                                       break;
+                               case GHOST_kKeyUpArrow:
+                                       if (val) {
+                                               ps->wait2 = FALSE;
+                                               if (g_WS.qual & WS_QUAL_SHIFT) {
+                                                       ps->next = ps->direction = 1;
+                                               }
+                                               else {
+                                                       ps->next = 10;
+                                                       ps->sstep = TRUE;
+                                               }
+                                       }
+                                       break;
+
+                               case GHOST_kKeySlash:
+                               case GHOST_kKeyNumpadSlash:
+                                       if (val) {
+                                               if (g_WS.qual & WS_QUAL_SHIFT) {
+                                                       if (ps->curframe_ibuf)
+                                                               printf(" Name: %s | Speed: %.2f frames/s\n", ps->curframe_ibuf->name, fstep / swaptime);
+                                               }
+                                               else {
+                                                       swaptime = fstep / 5.0;
+                                               }
+                                       }
+                                       break;
+                               case GHOST_kKeyEqual:
+                                       if (val) {
+                                               if (g_WS.qual & WS_QUAL_SHIFT) {
+                                                       ps->pause++;
+                                                       printf("pause:%d\n", ps->pause);
+                                               }
+                                               else {
+                                                       swaptime /= 1.1;
+                                               }
+                                       }
+                                       break;
+                               case GHOST_kKeyMinus:
+                                       if (val) {
+                                               if (g_WS.qual & WS_QUAL_SHIFT) {
+                                                       ps->pause--;
+                                                       printf("pause:%d\n", ps->pause);
+                                               }
+                                               else {
+                                                       swaptime *= 1.1;
+                                               }
+                                       }
+                                       break;
+                               case GHOST_kKeyNumpad0:
+                                       if (val) {
+                                               if (ps->once) {
+                                                       ps->once = ps->wait2 = FALSE;
+                                               }
+                                               else {
+                                                       ps->picture = NULL;
+                                                       ps->once = TRUE;
+                                                       ps->wait2 = FALSE;
+                                               }
+                                       }
+                                       break;
+                               case GHOST_kKeyEnter:
+                               case GHOST_kKeyNumpadEnter:
+                                       if (val) {
+                                               ps->wait2 = ps->sstep = FALSE;
+                                       }
+                                       break;
+                               case GHOST_kKeyNumpadPeriod:
+                                       if (val) {
+                                               if (ps->sstep) ps->wait2 = FALSE;
+                                               else {
+                                                       ps->sstep = TRUE;
+                                                       ps->wait2 = !ps->wait2;
+                                               }
+                                       }
+                                       break;
+                               case GHOST_kKeyNumpadPlus:
+                                       if (val == 0) break;
+                                       zoomx += 2.0;
+                                       zoomy += 2.0;
+                                       /* no break??? - is this intentional? - campbell XXX25 */
+                               case GHOST_kKeyNumpadMinus:
+                               {
+                                       int sizex, sizey;
+                                       /* int ofsx, ofsy; */ /* UNUSED */
+
+                                       if (val == 0) break;
+                                       if (zoomx > 1.0) zoomx -= 1.0;
+                                       if (zoomy > 1.0) zoomy -= 1.0;
+                                       // 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;
+                                       /* ofsx -= sizex / 2; */ /* UNUSED */
+                                       /* ofsy -= sizey / 2; */ /* UNUSED */
+                                       // window_set_position(g_WS.ghost_window,sizex,sizey);
+                                       GHOST_SetClientSize(g_WS.ghost_window, sizex, sizey);
+                                       break;
+                               }
+                               case GHOST_kKeyEsc:
+                                       ps->go = FALSE;
+                                       break;
+                               default:
+                                       break;
+                       }
+                       break;
+               }
+               case GHOST_kEventCursorMove:
+               {
+                       if (g_WS.qual & WS_QUAL_LMOUSE) {
+                               int sizex, sizey;
+                               int i;
+
+                               GHOST_TEventCursorData *cd = GHOST_GetEventData(evt);
+                               int cx, cy;
+
+                               GHOST_ScreenToClient(g_WS.ghost_window, cd->x, cd->y, &cx, &cy);
+
+                               playanim_window_get_size(&sizex, &sizey);
+                               ps->picture = picsbase.first;
+                               /* TODO - store in ps direct? */
+                               i = 0;
+                               while (ps->picture) {
+                                       i++;
+                                       ps->picture = ps->picture->next;
+                               }
+                               i = (i * cx) / sizex;
+                               ps->picture = picsbase.first;
+                               for (; i > 0; i--) {
+                                       if (ps->picture->next == NULL) break;
+                                       ps->picture = ps->picture->next;
+                               }
+                               ps->sstep = TRUE;
+                               ps->wait2 = FALSE;
+                               ps->next = 0;
+                       }
+                       break;
+               }
+               case GHOST_kEventWindowSize:
+               case GHOST_kEventWindowMove:
+               {
+                       int sizex, sizey;
+
+                       playanim_window_get_size(&sizex, &sizey);
+                       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.5);
+                       zoomy = floor(zoomy + 0.5);
+                       if (zoomx < 1.0) zoomx = 1.0;
+                       if (zoomy < 1.0) zoomy = 1.0;
+
+                       sizex = zoomx * ps->ibufx;
+                       sizey = zoomy * ps->ibufy;
+
+                       glPixelZoom(zoomx, zoomy);
+                       glEnable(GL_DITHER);
+                       ptottime = 0.0;
+                       playanim_toscreen(ps->picture, ps->curframe_ibuf, ps->fontid);
+
+                       break;
+               }
+               case GHOST_kEventQuit:
+               case GHOST_kEventWindowClose:
+               {
+                       ps->go = FALSE;
+                       break;
+               }
+               default:
+                       /* quiet warnings */
+                       break;
+       }
+
+       return 1;
+}
+
+void playanim_window_open(const char *title, int posx, int posy, int sizex, int sizey, int start_maximized)
+{
+       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;
+#if defined(__APPLE__) && !defined(GHOST_COCOA)
+       {
+               extern int macPrefState; /* creator.c */
+               initial_state += macPrefState;
+       }
+#endif
+
+       g_WS.ghost_window = GHOST_CreateWindow(g_WS.ghost_system,
+                                     title,
+                                     posx, posy, sizex, sizey,
+                                     inital_state,
+                                     GHOST_kDrawingContextTypeOpenGL,
+                                     FALSE /* no stereo */, FALSE);
+
+       //if (ghostwin) {
+       //if (win) {
+       // GHOST_SetWindowUserData(ghostwin, win);
+       //} else {
+       //      GHOST_DisposeWindow(g_WS.ghost_system, ghostwin);
+       //}
+       //}
+}
+
+
+void playanim(int argc, const char **argv)
+{
+       struct ImBuf *ibuf = NULL;
+       char filepath[FILE_MAX];
+       GHOST_TUns32 maxwinx, maxwiny;
+       /* short c233 = FALSE, yuvx = FALSE; */ /* UNUSED */
+       int i;
+       /* This was done to disambiguate the name for use under c++. */
+       struct anim *anim = NULL;
+       int start_x = 0, start_y = 0;
+       int sfra = -1;
+       int efra = -1;
+       int totblock;
+
+       PlayState ps = {0};
+
+       /* ps.doubleb   = TRUE;*/ /* UNUSED */
+       ps.go        = TRUE;
+       ps.direction = TRUE;
+       ps.next      = TRUE;
+       ps.once      = FALSE;
+       ps.turbo     = FALSE;
+       ps.pingpong  = FALSE;
+       ps.noskip    = FALSE;
+       ps.sstep     = FALSE;
+       ps.pause     = FALSE;
+       ps.wait2     = FALSE;
+       ps.stopped   = FALSE;
+       ps.picture   = NULL;
+       /* resetmap = FALSE */
+
+       ps.fontid = -1;
+
+       while (argc > 1) {
+               if (argv[1][0] == '-') {
+                       switch (argv[1][1]) {
+                               case 'm':
+                                       fromdisk = TRUE;
+                                       break;
+                               case 'p':
+                                       if (argc > 3) {
+                                               start_x = atoi(argv[2]);
+                                               start_y = atoi(argv[3]);
+                                               argc -= 2;
+                                               argv += 2;
+                                       }
+                                       else {
+                                               printf("too few arguments for -p (need 2): skipping\n");
+                                       }
+                                       break;
+                               case 'f':
+                                       if (argc > 3) {
+                                               double fps = atof(argv[2]);
+                                               double fps_base = atof(argv[3]);
+                                               if (fps == 0.0) {
+                                                       fps = 1;
+                                                       printf("invalid fps,"
+                                                              "forcing 1\n");
+                                               }
+                                               swaptime = fps_base / fps;
+                                               argc -= 2;
+                                               argv += 2;
+                                       }
+                                       else {
+                                               printf("too few arguments for -f (need 2): skipping\n");
+                                       }
+                                       break;
+                               case 's':
+                                       sfra = MIN2(MAXFRAME, MAX2(1, atoi(argv[2]) ));
+                                       argc--;
+                                       argv++;
+                                       break;
+                               case 'e':
+                                       efra = MIN2(MAXFRAME, MAX2(1, atoi(argv[2]) ));
+                                       argc--;
+                                       argv++;
+                                       break;
+                               case 'j':
+                                       fstep = MIN2(MAXFRAME, MAX2(1, atoi(argv[2])));
+                                       swaptime *= fstep;
+                                       argc--;
+                                       argv++;
+                                       break;
+                               default:
+                                       printf("unknown option '%c': skipping\n", argv[1][1]);
+                                       break;
+                       }
+                       argc--;
+                       argv++;
+               }
+               else {
+                       break;
+               }
+       }
+
+#ifdef WITH_QUICKTIME
+#if defined(_WIN32) || defined(__APPLE__) && !defined(GHOST_COCOA)
+       /* Initialize QuickTime */
+#ifndef noErr
+#define noErr 0
+#endif
+
+#ifdef _WIN32
+       if (InitializeQTML(0) != noErr)
+               G.have_quicktime = FALSE;
+       else
+               G.have_quicktime = TRUE;
+#endif /* _WIN32 */
+       if (EnterMovies() != noErr)
+               G.have_quicktime = FALSE;
+       else
+#endif /* _WIN32 || __APPLE__  && !defined(GHOST_COCOA)*/
+       G.have_quicktime = TRUE;
+#endif /* WITH_QUICKTIME */
+
+       if (argc > 1) {
+               BLI_strncpy(filepath, argv[1], sizeof(filepath));
+       }
+       else {
+               BLI_current_working_dir(filepath, sizeof(filepath));
+               BLI_add_slash(filepath);
+       }
+
+       if (IMB_isanim(filepath)) {
+               anim = IMB_open_anim(filepath, IB_rect, 0);
+               if (anim) {
+                       ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
+                       IMB_close_anim(anim);
+                       anim = NULL;
+               }
+       }
+       else if (!IMB_ispic(filepath)) {
+               exit(1);
+       }
+
+       if (ibuf == NULL) {
+               ibuf = IMB_loadiffname(filepath, IB_rect);
+       }
+
+       if (ibuf == NULL) {
+               printf("couldn't open %s\n", filepath);
+               exit(1);
+       }
+
+#if 0 //XXX25
+       #if !defined(WIN32) && !defined(__APPLE__)
+       if (fork()) exit(0);
+       #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, 0);
+//XXX25                window_set_handler(g_WS.ghost_window, add_to_mainqueue, NULL);
+
+               glMatrixMode(GL_PROJECTION);
+               glLoadIdentity();
+               glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
+               glMatrixMode(GL_MODELVIEW);
+       }
+
+       GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &maxwinx, &maxwiny);
+
+       //GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);
+
+       /* initialize the font */
+       BLF_init(11, 72);
+       ps.fontid = BLF_load_mem("monospace", (unsigned char *)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size);
+       BLF_size(ps.fontid, 11, 72);
+
+       ps.ibufx = ibuf->x;
+       ps.ibufy = ibuf->y;
+
+       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);
+       glClear(GL_COLOR_BUFFER_BIT);
+
+       GHOST_SwapWindowBuffers(g_WS.ghost_window);
+
+       if (sfra == -1 || efra == -1) {
+               /* one of the frames was invalid, just use all images */
+               sfra = 1;
+               efra = MAXFRAME;
+       }
+
+       build_pict_list(filepath, (efra - sfra) + 1, fstep, ps.fontid);
+
+       for (i = 2; i < argc; i++) {
+               BLI_strncpy(filepath, argv[i], sizeof(filepath));
+               build_pict_list(filepath, (efra - sfra) + 1, fstep, ps.fontid);
+       }
+
+       IMB_freeImBuf(ibuf);
+       ibuf = NULL;
+
+       pupdate_time();
+       ptottime = 0;
+
+       /* newly added in 2.6x, without this images never get freed */
+#define USE_IMB_CACHE
+
+       while (ps.go) {
+               if (ps.pingpong)
+                       ps.direction = -ps.direction;
+
+               if (ps.direction == 1) {
+                       ps.picture = picsbase.first;
+               }
+               else {
+                       ps.picture = picsbase.last;
+               }
+
+               if (ps.picture == NULL) {
+                       printf("couldn't find pictures\n");
+                       ps.go = FALSE;
+               }
+               if (ps.pingpong) {
+                       if (ps.direction == 1) {
+                               ps.picture = ps.picture->next;
+                       }
+                       else {
+                               ps.picture = ps.picture->prev;
+                       }
+               }
+               if (ptottime > 0.0) ptottime = 0.0;
+
+               while (ps.picture) {
+#ifndef USE_IMB_CACHE
+                       if (ibuf != NULL && ibuf->ftype == 0) IMB_freeImBuf(ibuf);
+#endif
+                       if (ps.picture->ibuf) {
+                               ibuf = ps.picture->ibuf;
+                       }
+                       else if (ps.picture->anim) {
+                               ibuf = IMB_anim_absolute(ps.picture->anim, ps.picture->frame, IMB_TC_NONE, IMB_PROXY_NONE);
+                       }
+                       else if (ps.picture->mem) {
+                               ibuf = IMB_ibImageFromMemory((unsigned char *) ps.picture->mem, ps.picture->size,
+                                                            ps.picture->IB_flags, ps.picture->name);
+                       }
+                       else {
+                               ibuf = IMB_loadiffname(ps.picture->name, ps.picture->IB_flags);
+                       }
+
+                       if (ibuf) {
+
+#ifdef USE_IMB_CACHE
+                               ps.picture->ibuf = ibuf;
+#endif
+
+                               BLI_strncpy(ibuf->name, ps.picture->name, sizeof(ibuf->name));
+
+                               /* why only windows? (from 2.4x) - campbell */
+#ifdef _WIN32
+                               GHOST_SetTitle(g_WS.ghost_window, ps.picture->name);
+#endif
+
+                               while (pupdate_time()) PIL_sleep_ms(1);
+                               ptottime -= swaptime;
+                               playanim_toscreen(ps.picture, ibuf, ps.fontid);
+                       } /* else deleten */
+                       else {
+                               printf("error: can't play this image type\n");
+                               exit(0);
+                       }
+
+                       if (ps.once) {
+                               if (ps.picture->next == NULL) {
+                                       ps.wait2 = TRUE;
+                               }
+                               else if (ps.picture->prev == NULL) {
+                                       ps.wait2 = TRUE;
+                               }
+                       }
+
+                       ps.next = ps.direction;
+
+
+                       {
+                               int hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0);
+                               if (hasevent) {
+                                       GHOST_DispatchEvents(g_WS.ghost_system);
+                               }
+                       }
+
+                       /* XXX25 - we should not have to do this, but it makes scrubbing functional! */
+                       if (g_WS.qual & WS_QUAL_LMOUSE) {
+                               ps.next = 0;
+                       }
+                       else {
+                               ps.sstep = 0;
+                       }
+
+                       ps.wait2 = ps.sstep;
+
+                       if (ps.wait2 == 0 && ps.stopped == 0) {
+                               ps.stopped = TRUE;
+                       }
+
+                       pupdate_time();
+
+                       if (ps.picture && ps.next) {
+                               /* always at least set one step */
+                               while (ps.picture) {
+                                       if (ps.next < 0) {
+                                               ps.picture = ps.picture->prev;
+                                       }
+                                       else {
+                                               ps.picture = ps.picture->next;
+                                       }
+
+                                       if (ps.once && ps.picture != NULL) {
+                                               if (ps.picture->next == NULL) {
+                                                       ps.wait2 = TRUE;
+                                               }
+                                               else if (ps.picture->prev == NULL) {
+                                                       ps.wait2 = TRUE;
+                                               }
+                                       }
+
+                                       if (ps.wait2 || ptottime < swaptime || ps.turbo || ps.noskip) break;
+                                       ptottime -= swaptime;
+                               }
+                               if (ps.picture == NULL && ps.sstep) {
+                                       if (ps.next < 0) {
+                                               ps.picture = picsbase.last;
+                                       }
+                                       else if (ps.next > 0) {
+                                               ps.picture = picsbase.first;
+                                       }
+                               }
+                       }
+                       if (ps.go == FALSE) {
+                               break;
+                       }
+               }
+       }
+       ps.picture = picsbase.first;
+       anim = NULL;
+       while (ps.picture) {
+               if (ps.picture && ps.picture->anim && (anim != ps.picture->anim)) {
+                       // to prevent divx crashes
+                       anim = ps.picture->anim;
+                       IMB_close_anim(anim);
+               }
+
+               if (ps.picture->ibuf) {
+                       IMB_freeImBuf(ps.picture->ibuf);
+               }
+               if (ps.picture->mem) {
+                       MEM_freeN(ps.picture->mem);
+               }
+
+               ps.picture = ps.picture->next;
+       }
+#ifdef WITH_QUICKTIME
+#if defined(_WIN32) || defined(__APPLE__) && !defined(GHOST_COCOA)
+       if (G.have_quicktime) {
+               ExitMovies();
+#ifdef _WIN32
+               TerminateQTML();
+#endif /* _WIN32 */
+       }
+#endif /* _WIN32 || __APPLE__ && !defined(GHOST_COCOA) */
+#endif /* WITH_QUICKTIME */
+
+       /* cleanup */
+#ifndef USE_IMB_CACHE
+       if (ibuf) IMB_freeImBuf(ibuf);
+#endif
+
+       BLI_freelistN(&picsbase);
+#if 0 // XXX25
+       free_blender();
+#else
+       /* we still miss freeing a lot!,
+        * but many areas could skip initialization too for anim play */
+       IMB_exit();
+       BLF_exit();
+#endif
+       GHOST_DisposeWindow(g_WS.ghost_system, g_WS.ghost_window);
+
+       totblock = MEM_get_memory_blocks_in_use();
+       if (totblock != 0) {
+               /* prints many bAKey, bArgument's which are tricky to fix */
+#if 0
+               printf("Error Totblock: %d\n", totblock);
+               MEM_printmemlist();
+#endif
+       }
+}
index 01c850412de9e4075479860daa62cc5bac635466..7479935c179ccb25db67661c704cf2760330c4b5 100644 (file)
@@ -453,16 +453,14 @@ static int set_env(int argc, const char **argv, void *UNUSED(data))
        return 1;
 }
 
-static int playback_mode(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
+static int playback_mode(int argc, const char **argv, void *UNUSED(data))
 {
+       extern void playanim(int argc, const char **argv);
+
        /* not if -b was given first */
        if (G.background == 0) {
-#if 0   /* TODO, bring player back? */
                playanim(argc, argv); /* not the same argc and argv as before */
-#else
-               fprintf(stderr, "Playback mode not supported in blender 2.6x\n");
-               exit(0);
-#endif
+               exit(0); /* 2.4x didn't do this */
        }
 
        return -2;
@@ -1272,11 +1270,6 @@ int main(int argc, const char **argv)
 
        BLI_threadapi_init();
 
-       RNA_init();
-       RE_engines_init();
-
-       init_nodesystem();
-       
        initglobals();  /* blender.c */
 
        IMB_init();
@@ -1297,6 +1290,15 @@ int main(int argc, const char **argv)
        BLI_argsParse(ba, 1, NULL, NULL);
 #endif
 
+
+       /* after level 1 args, this is so playanim skips RNA init */
+       RNA_init();
+
+       RE_engines_init();
+       init_nodesystem();
+       /* end second init */
+
+
 #if defined(WITH_PYTHON_MODULE) || defined(WITH_HEADLESS)
        G.background = 1; /* python module mode ALWAYS runs in background mode (for now) */
 #else