bring back the play option from 2.4x

This commit is contained in:
Campbell Barton
2012-08-06 16:07:11 +00:00
parent 48b59330fe
commit db6c4ba11e
7 changed files with 1156 additions and 42 deletions

View 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)

View 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")

View 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;

View 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"},

View 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

View File

@@ -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
}
}

View 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