2012-08-06 16:07:11 +00:00
|
|
|
/*
|
|
|
|
|
* 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,
|
2013-09-12 03:02:50 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2012-08-06 16:07:11 +00:00
|
|
|
*
|
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*/
|
|
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup wm
|
2012-08-06 16:07:11 +00:00
|
|
|
*
|
2018-07-15 20:29:11 +02:00
|
|
|
* Animation player for image sequences & video's with sound support.
|
|
|
|
|
* Launched in a separate process from Blender's #RENDER_OT_play_rendered_anim
|
|
|
|
|
*
|
2012-08-06 16:07:11 +00:00
|
|
|
* \note This file uses ghost directly and none of the WM definitions.
|
2018-07-15 20:29:11 +02:00
|
|
|
* this could be made into its own module, alongside creator.
|
2012-08-06 16:07:11 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <fcntl.h>
|
2020-03-19 09:33:03 +01:00
|
|
|
#include <math.h>
|
2012-08-06 16:07:11 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
2020-03-19 09:33:03 +01:00
|
|
|
#include <sys/types.h>
|
2012-08-06 16:07:11 +00:00
|
|
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
|
# include <sys/times.h>
|
|
|
|
|
# include <sys/wait.h>
|
2020-03-19 09:33:03 +01:00
|
|
|
# include <unistd.h>
|
2012-08-06 16:07:11 +00:00
|
|
|
#else
|
|
|
|
|
# include <io.h>
|
|
|
|
|
#endif
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
|
|
#include "PIL_time.h"
|
|
|
|
|
|
2012-08-21 10:24:30 +00:00
|
|
|
#include "BLI_fileops.h"
|
2012-08-06 16:07:11 +00:00
|
|
|
#include "BLI_listbase.h"
|
|
|
|
|
#include "BLI_path_util.h"
|
2021-05-07 09:43:26 +02:00
|
|
|
#include "BLI_rect.h"
|
2012-08-21 10:24:30 +00:00
|
|
|
#include "BLI_string.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_utildefines.h"
|
2012-08-06 16:07:11 +00:00
|
|
|
|
2021-05-07 09:43:26 +02:00
|
|
|
#include "IMB_colormanagement.h"
|
2012-08-06 16:07:11 +00:00
|
|
|
#include "IMB_imbuf.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "IMB_imbuf_types.h"
|
2012-08-06 16:07:11 +00:00
|
|
|
|
2012-11-15 15:59:58 +00:00
|
|
|
#include "BKE_image.h"
|
2012-08-06 16:07:11 +00:00
|
|
|
|
2017-04-11 01:21:15 +10:00
|
|
|
#include "BIF_glutil.h"
|
2012-08-06 16:07:11 +00:00
|
|
|
|
2019-03-25 20:26:52 +01:00
|
|
|
#include "GPU_context.h"
|
2020-07-16 02:06:25 +02:00
|
|
|
#include "GPU_framebuffer.h"
|
2017-04-06 01:54:10 -03:00
|
|
|
#include "GPU_immediate.h"
|
2017-04-05 18:30:14 +10:00
|
|
|
#include "GPU_immediate_util.h"
|
2018-07-01 21:07:18 +02:00
|
|
|
#include "GPU_init_exit.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "GPU_matrix.h"
|
2019-03-25 20:26:52 +01:00
|
|
|
#include "GPU_state.h"
|
2017-03-21 02:51:02 -04:00
|
|
|
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLF_api.h"
|
2012-08-06 16:07:11 +00:00
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
|
#include "ED_datafiles.h" /* for fonts */
|
|
|
|
|
#include "GHOST_C-api.h"
|
|
|
|
|
|
2017-04-06 16:44:32 +02:00
|
|
|
#include "DEG_depsgraph.h"
|
|
|
|
|
|
2012-09-15 01:52:28 +00:00
|
|
|
#include "WM_api.h" /* only for WM_main_playanim */
|
|
|
|
|
|
2015-06-12 11:47:37 +02:00
|
|
|
#ifdef WITH_AUDASPACE
|
2017-08-18 08:24:12 +02:00
|
|
|
# include <AUD_Device.h>
|
|
|
|
|
# include <AUD_Handle.h>
|
|
|
|
|
# include <AUD_Sound.h>
|
|
|
|
|
# include <AUD_Special.h>
|
2015-06-12 11:47:37 +02:00
|
|
|
|
2015-09-03 04:12:03 +10:00
|
|
|
static AUD_Sound *source = NULL;
|
|
|
|
|
static AUD_Handle *playback_handle = NULL;
|
|
|
|
|
static AUD_Handle *scrub_handle = NULL;
|
|
|
|
|
static AUD_Device *audio_device = NULL;
|
2015-06-12 11:47:37 +02:00
|
|
|
#endif
|
|
|
|
|
|
2015-05-16 08:34:36 +10:00
|
|
|
/* simple limiter to avoid flooding memory */
|
|
|
|
|
#define USE_FRAME_CACHE_LIMIT
|
|
|
|
|
#ifdef USE_FRAME_CACHE_LIMIT
|
|
|
|
|
# define PLAY_FRAME_CACHE_MAX 30
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-11-17 06:05:37 +00:00
|
|
|
struct PlayState;
|
2013-03-09 14:57:06 +00:00
|
|
|
static void playanim_window_zoom(struct PlayState *ps, const float zoom_offset);
|
2012-11-17 06:05:37 +00:00
|
|
|
|
2021-05-10 15:30:20 +10:00
|
|
|
/**
|
|
|
|
|
* The current state of the player.
|
|
|
|
|
*
|
|
|
|
|
* \warning Don't store results of parsing command-line arguments
|
|
|
|
|
* in this struct if they need to persist across playing back different
|
|
|
|
|
* files as these will be cleared when playing other files (drag & drop).
|
|
|
|
|
*/
|
2012-08-06 16:07:11 +00:00
|
|
|
typedef struct PlayState {
|
|
|
|
|
|
2021-05-08 15:50:34 +10:00
|
|
|
/** Window and viewport size. */
|
2013-03-09 14:57:06 +00:00
|
|
|
int win_x, win_y;
|
2018-06-07 16:43:52 +02:00
|
|
|
|
2021-05-08 15:50:34 +10:00
|
|
|
/** Current zoom level. */
|
2013-03-09 14:57:06 +00:00
|
|
|
float zoom;
|
|
|
|
|
|
2021-05-08 15:50:34 +10:00
|
|
|
/** Playback direction (-1, 1). */
|
2012-08-06 16:07:11 +00:00
|
|
|
short direction;
|
2021-05-08 15:50:34 +10:00
|
|
|
/** Set the next frame to implement frame stepping (using shortcuts). */
|
2012-12-06 06:01:15 +00:00
|
|
|
short next_frame;
|
2014-04-01 11:34:00 +11:00
|
|
|
|
2021-05-08 15:50:34 +10:00
|
|
|
/** Playback once then wait. */
|
2014-04-01 11:34:00 +11:00
|
|
|
bool once;
|
2021-05-08 15:50:34 +10:00
|
|
|
/** Play forwards/backwards. */
|
2014-04-01 11:34:00 +11:00
|
|
|
bool pingpong;
|
2021-05-08 15:50:34 +10:00
|
|
|
/** Disable frame skipping. */
|
2014-04-01 11:34:00 +11:00
|
|
|
bool noskip;
|
2021-05-08 15:50:34 +10:00
|
|
|
/** Display current frame over the window. */
|
2015-06-12 11:47:37 +02:00
|
|
|
bool indicator;
|
2021-05-08 15:50:34 +10:00
|
|
|
/** Single-frame stepping has been enabled (frame loading and update pending). */
|
2014-04-01 11:34:00 +11:00
|
|
|
bool sstep;
|
2021-05-08 15:50:34 +10:00
|
|
|
/** Playback has stopped the image has been displayed. */
|
2014-04-01 11:34:00 +11:00
|
|
|
bool wait2;
|
2021-05-08 15:50:34 +10:00
|
|
|
/** Playback stopped state once stop/start variables have been handled. */
|
2014-04-01 11:34:00 +11:00
|
|
|
bool stopped;
|
2021-05-10 15:30:20 +10:00
|
|
|
/**
|
|
|
|
|
* When disabled the current animation will exit,
|
|
|
|
|
* after this either the application exits or a new animation window is opened.
|
|
|
|
|
*
|
|
|
|
|
* This is used so drag & drop can load new files which setup a newly created animation window.
|
|
|
|
|
*/
|
2014-04-01 11:34:00 +11:00
|
|
|
bool go;
|
2021-05-08 15:50:34 +10:00
|
|
|
/** True when waiting for images to load. */
|
2014-05-07 18:18:21 +10:00
|
|
|
bool loading;
|
2021-05-08 15:50:34 +10:00
|
|
|
/** X/Y image flip (set via key bindings). */
|
2014-10-01 21:59:02 +10:00
|
|
|
bool draw_flip[2];
|
2018-06-07 16:43:52 +02:00
|
|
|
|
2021-05-08 15:50:34 +10:00
|
|
|
/** The number of frames to step each update (default to 1, command line argument). */
|
2012-10-12 14:03:43 +00:00
|
|
|
int fstep;
|
|
|
|
|
|
2021-05-08 15:50:34 +10:00
|
|
|
/** Current frame (picture). */
|
2012-08-06 16:07:11 +00:00
|
|
|
struct PlayAnimPict *picture;
|
|
|
|
|
|
2021-05-08 15:50:34 +10:00
|
|
|
/** Image size in pixels, set once at the start. */
|
2012-08-06 16:07:11 +00:00
|
|
|
int ibufx, ibufy;
|
2021-05-08 15:50:34 +10:00
|
|
|
/** Mono-space font ID. */
|
2012-08-06 16:07:11 +00:00
|
|
|
int fontid;
|
|
|
|
|
|
2021-05-08 15:50:34 +10:00
|
|
|
/** Restarts player for file drop (drag & drop). */
|
2013-03-08 13:03:04 +00:00
|
|
|
char dropped_file[FILE_MAX];
|
2018-07-06 17:14:16 +02:00
|
|
|
|
2021-05-08 15:50:34 +10:00
|
|
|
/** Force update when scrubbing with the cursor. */
|
2018-07-06 17:14:16 +02:00
|
|
|
bool need_frame_update;
|
2021-05-08 15:50:34 +10:00
|
|
|
/** The current frame calculated by scrubbing the mouse cursor. */
|
2018-07-06 17:14:16 +02:00
|
|
|
int frame_cursor_x;
|
2021-05-07 09:43:26 +02:00
|
|
|
|
|
|
|
|
ColorManagedViewSettings view_settings;
|
|
|
|
|
ColorManagedDisplaySettings display_settings;
|
2012-08-06 16:07:11 +00:00
|
|
|
} PlayState;
|
|
|
|
|
|
|
|
|
|
/* for debugging */
|
|
|
|
|
#if 0
|
2021-05-08 15:50:34 +10:00
|
|
|
static void print_ps(PlayState *ps)
|
2012-08-06 16:07:11 +00:00
|
|
|
{
|
|
|
|
|
printf("ps:\n");
|
|
|
|
|
printf(" direction=%d,\n", (int)ps->direction);
|
|
|
|
|
printf(" once=%d,\n", ps->once);
|
|
|
|
|
printf(" pingpong=%d,\n", ps->pingpong);
|
|
|
|
|
printf(" noskip=%d,\n", ps->noskip);
|
|
|
|
|
printf(" sstep=%d,\n", ps->sstep);
|
|
|
|
|
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),
|
2012-11-17 06:32:35 +00:00
|
|
|
WS_QUAL_CTRL = (WS_QUAL_LCTRL | WS_QUAL_RCTRL),
|
2012-08-06 16:07:11 +00:00
|
|
|
WS_QUAL_LMOUSE = (1 << 16),
|
|
|
|
|
WS_QUAL_MMOUSE = (1 << 17),
|
|
|
|
|
WS_QUAL_RMOUSE = (1 << 18),
|
2019-01-15 23:57:49 +11:00
|
|
|
WS_QUAL_MOUSE = (WS_QUAL_LMOUSE | WS_QUAL_MMOUSE | WS_QUAL_RMOUSE),
|
2012-08-06 16:07:11 +00:00
|
|
|
} eWS_Qual;
|
|
|
|
|
|
|
|
|
|
static struct WindowStateGlobal {
|
|
|
|
|
GHOST_SystemHandle ghost_system;
|
|
|
|
|
void *ghost_window;
|
2018-07-18 00:12:21 +02:00
|
|
|
GPUContext *gpu_context;
|
2012-08-06 16:07:11 +00:00
|
|
|
|
|
|
|
|
/* events */
|
|
|
|
|
eWS_Qual qual;
|
|
|
|
|
} g_WS = {NULL};
|
|
|
|
|
|
2015-05-08 07:25:39 +10:00
|
|
|
static void playanim_window_get_size(int *r_width, int *r_height)
|
2012-08-06 16:07:11 +00:00
|
|
|
{
|
|
|
|
|
GHOST_RectangleHandle bounds = GHOST_GetClientBounds(g_WS.ghost_window);
|
2015-05-08 07:25:39 +10:00
|
|
|
*r_width = GHOST_GetWidthRectangle(bounds);
|
|
|
|
|
*r_height = GHOST_GetHeightRectangle(bounds);
|
2012-08-06 16:07:11 +00:00
|
|
|
GHOST_DisposeRectangle(bounds);
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-01 20:45:05 +10:00
|
|
|
static void playanim_gl_matrix(void)
|
|
|
|
|
{
|
|
|
|
|
/* unified matrix, note it affects offset for drawing */
|
2018-07-15 15:27:15 +02:00
|
|
|
/* note! cannot use GPU_matrix_ortho_2d_set here because shader ignores. */
|
|
|
|
|
GPU_matrix_ortho_set(0.0f, 1.0f, 0.0f, 1.0f, -1.0, 1.0f);
|
2014-10-01 20:45:05 +10:00
|
|
|
}
|
|
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
/* implementation */
|
|
|
|
|
static void playanim_event_qual_update(void)
|
|
|
|
|
{
|
|
|
|
|
int val;
|
|
|
|
|
|
|
|
|
|
/* Shift */
|
|
|
|
|
GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyLeftShift, &val);
|
2019-01-25 00:34:36 +11:00
|
|
|
SET_FLAG_FROM_TEST(g_WS.qual, val, WS_QUAL_LSHIFT);
|
2012-08-06 16:07:11 +00:00
|
|
|
|
|
|
|
|
GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyRightShift, &val);
|
2019-01-25 00:34:36 +11:00
|
|
|
SET_FLAG_FROM_TEST(g_WS.qual, val, WS_QUAL_RSHIFT);
|
2012-08-06 16:07:11 +00:00
|
|
|
|
|
|
|
|
/* Control */
|
|
|
|
|
GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyLeftControl, &val);
|
2019-01-25 00:34:36 +11:00
|
|
|
SET_FLAG_FROM_TEST(g_WS.qual, val, WS_QUAL_LCTRL);
|
2012-08-06 16:07:11 +00:00
|
|
|
|
|
|
|
|
GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyRightControl, &val);
|
2019-01-25 00:34:36 +11:00
|
|
|
SET_FLAG_FROM_TEST(g_WS.qual, val, WS_QUAL_RCTRL);
|
2012-08-06 16:07:11 +00:00
|
|
|
|
|
|
|
|
/* Alt */
|
|
|
|
|
GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyLeftAlt, &val);
|
2019-01-25 00:34:36 +11:00
|
|
|
SET_FLAG_FROM_TEST(g_WS.qual, val, WS_QUAL_LALT);
|
2012-08-06 16:07:11 +00:00
|
|
|
|
|
|
|
|
GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyRightAlt, &val);
|
2019-01-25 00:34:36 +11:00
|
|
|
SET_FLAG_FROM_TEST(g_WS.qual, val, WS_QUAL_RALT);
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef struct PlayAnimPict {
|
|
|
|
|
struct PlayAnimPict *next, *prev;
|
2019-03-25 09:08:29 +11:00
|
|
|
uchar *mem;
|
2012-08-06 16:07:11 +00:00
|
|
|
int size;
|
2014-04-27 00:21:43 +10:00
|
|
|
const char *name;
|
2012-08-06 16:07:11 +00:00
|
|
|
struct ImBuf *ibuf;
|
|
|
|
|
struct anim *anim;
|
|
|
|
|
int frame;
|
|
|
|
|
int IB_flags;
|
2021-05-05 17:57:32 +10:00
|
|
|
|
|
|
|
|
#ifdef USE_FRAME_CACHE_LIMIT
|
2021-05-07 17:12:41 +10:00
|
|
|
/** Back pointer to the #LinkData node for this struct in the #g_frame_cache.pics list. */
|
2021-05-05 17:57:32 +10:00
|
|
|
LinkData *frame_cache_node;
|
2021-05-06 11:22:54 +10:00
|
|
|
size_t size_in_memory;
|
2021-05-05 17:57:32 +10:00
|
|
|
#endif
|
2012-08-06 16:07:11 +00:00
|
|
|
} PlayAnimPict;
|
|
|
|
|
|
|
|
|
|
static struct ListBase picsbase = {NULL, NULL};
|
2015-05-15 16:00:36 +02:00
|
|
|
/* frames in memory - store them here to for easy deallocation later */
|
2014-04-01 11:34:00 +11:00
|
|
|
static bool fromdisk = false;
|
2012-08-06 16:07:11 +00:00
|
|
|
static double ptottime = 0.0, swaptime = 0.04;
|
2015-06-12 15:29:09 +02:00
|
|
|
#ifdef WITH_AUDASPACE
|
2015-06-12 11:47:37 +02:00
|
|
|
static double fps_movie;
|
2015-06-12 15:29:09 +02:00
|
|
|
#endif
|
2012-08-06 16:07:11 +00:00
|
|
|
|
2015-05-16 08:34:36 +10:00
|
|
|
#ifdef USE_FRAME_CACHE_LIMIT
|
2021-05-07 17:12:41 +10:00
|
|
|
static struct {
|
|
|
|
|
/** A list of #LinkData nodes referencing #PlayAnimPict to track cached frames. */
|
|
|
|
|
struct ListBase pics;
|
|
|
|
|
/** Number if elements in `pics`. */
|
|
|
|
|
int pics_len;
|
|
|
|
|
/** Keep track of memory used by #g_frame_cache.pics when `g_frame_cache.memory_limit != 0`. */
|
|
|
|
|
size_t pics_size_in_memory;
|
|
|
|
|
/** Optionally limit the amount of memory used for cache (in bytes), ignored when zero. */
|
|
|
|
|
size_t memory_limit;
|
|
|
|
|
} g_frame_cache = {
|
|
|
|
|
.pics = {NULL, NULL},
|
|
|
|
|
.pics_len = 0,
|
|
|
|
|
.pics_size_in_memory = 0,
|
|
|
|
|
.memory_limit = 0,
|
|
|
|
|
};
|
2021-05-07 17:53:27 +10:00
|
|
|
|
|
|
|
|
static void frame_cache_add(PlayAnimPict *pic)
|
|
|
|
|
{
|
|
|
|
|
pic->frame_cache_node = BLI_genericNodeN(pic);
|
|
|
|
|
BLI_addhead(&g_frame_cache.pics, pic->frame_cache_node);
|
|
|
|
|
g_frame_cache.pics_len++;
|
|
|
|
|
|
|
|
|
|
if (g_frame_cache.memory_limit != 0) {
|
|
|
|
|
BLI_assert(pic->size_in_memory == 0);
|
|
|
|
|
pic->size_in_memory = IMB_get_size_in_memory(pic->ibuf);
|
|
|
|
|
g_frame_cache.pics_size_in_memory += pic->size_in_memory;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void frame_cache_remove(PlayAnimPict *pic)
|
|
|
|
|
{
|
|
|
|
|
LinkData *node = pic->frame_cache_node;
|
|
|
|
|
IMB_freeImBuf(pic->ibuf);
|
|
|
|
|
if (g_frame_cache.memory_limit != 0) {
|
|
|
|
|
BLI_assert(pic->size_in_memory != 0);
|
|
|
|
|
g_frame_cache.pics_size_in_memory -= pic->size_in_memory;
|
|
|
|
|
pic->size_in_memory = 0;
|
|
|
|
|
}
|
|
|
|
|
pic->ibuf = NULL;
|
|
|
|
|
pic->frame_cache_node = NULL;
|
|
|
|
|
BLI_freelinkN(&g_frame_cache.pics, node);
|
|
|
|
|
g_frame_cache.pics_len--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Don't free the current frame by moving it to the head of the list. */
|
|
|
|
|
static void frame_cache_touch(PlayAnimPict *pic)
|
|
|
|
|
{
|
|
|
|
|
BLI_assert(pic->frame_cache_node->data == pic);
|
|
|
|
|
BLI_remlink(&g_frame_cache.pics, pic->frame_cache_node);
|
|
|
|
|
BLI_addhead(&g_frame_cache.pics, pic->frame_cache_node);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool frame_cache_limit_exceeded(void)
|
|
|
|
|
{
|
|
|
|
|
return g_frame_cache.memory_limit ?
|
|
|
|
|
(g_frame_cache.pics_size_in_memory > g_frame_cache.memory_limit) :
|
|
|
|
|
(g_frame_cache.pics_len > PLAY_FRAME_CACHE_MAX);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void frame_cache_limit_apply(ImBuf *ibuf_keep)
|
|
|
|
|
{
|
|
|
|
|
/* Really basic memory conservation scheme. Keep frames in a FIFO queue. */
|
|
|
|
|
LinkData *node = g_frame_cache.pics.last;
|
|
|
|
|
while (node && frame_cache_limit_exceeded()) {
|
|
|
|
|
PlayAnimPict *pic = node->data;
|
|
|
|
|
BLI_assert(pic->frame_cache_node == node);
|
|
|
|
|
|
|
|
|
|
node = node->prev;
|
|
|
|
|
if (pic->ibuf && pic->ibuf != ibuf_keep) {
|
|
|
|
|
frame_cache_remove(pic);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-07 17:12:41 +10:00
|
|
|
#endif /* USE_FRAME_CACHE_LIMIT */
|
2015-05-16 08:34:36 +10:00
|
|
|
|
2021-05-07 17:49:14 +10:00
|
|
|
static ImBuf *ibuf_from_picture(PlayAnimPict *pic)
|
|
|
|
|
{
|
|
|
|
|
ImBuf *ibuf = NULL;
|
|
|
|
|
|
|
|
|
|
if (pic->ibuf) {
|
|
|
|
|
ibuf = pic->ibuf;
|
|
|
|
|
}
|
|
|
|
|
else if (pic->anim) {
|
|
|
|
|
ibuf = IMB_anim_absolute(pic->anim, pic->frame, IMB_TC_NONE, IMB_PROXY_NONE);
|
|
|
|
|
}
|
|
|
|
|
else if (pic->mem) {
|
|
|
|
|
/* use correct colorspace here */
|
|
|
|
|
ibuf = IMB_ibImageFromMemory(pic->mem, pic->size, pic->IB_flags, NULL, pic->name);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* use correct colorspace here */
|
|
|
|
|
ibuf = IMB_loadiffname(pic->name, pic->IB_flags, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ibuf;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-06 06:01:15 +00:00
|
|
|
static PlayAnimPict *playanim_step(PlayAnimPict *playanim, int step)
|
|
|
|
|
{
|
|
|
|
|
if (step > 0) {
|
|
|
|
|
while (step-- && playanim) {
|
|
|
|
|
playanim = playanim->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (step < 0) {
|
|
|
|
|
while (step++ && playanim) {
|
|
|
|
|
playanim = playanim->prev;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return playanim;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
static int pupdate_time(void)
|
|
|
|
|
{
|
|
|
|
|
static double ltime;
|
|
|
|
|
|
2020-10-17 16:36:02 -05:00
|
|
|
double time = PIL_check_seconds_timer();
|
2012-08-06 16:07:11 +00:00
|
|
|
|
|
|
|
|
ptottime += (time - ltime);
|
|
|
|
|
ltime = time;
|
|
|
|
|
return (ptottime < 0);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-07 09:43:26 +02:00
|
|
|
static void *ocio_transform_ibuf(PlayState *ps,
|
|
|
|
|
ImBuf *ibuf,
|
|
|
|
|
bool *r_glsl_used,
|
|
|
|
|
eGPUTextureFormat *r_format,
|
|
|
|
|
eGPUDataFormat *r_data,
|
|
|
|
|
void **r_buffer_cache_handle)
|
|
|
|
|
{
|
|
|
|
|
void *display_buffer;
|
|
|
|
|
bool force_fallback = false;
|
|
|
|
|
*r_glsl_used = false;
|
|
|
|
|
force_fallback |= (ED_draw_imbuf_method(ibuf) != IMAGE_DRAW_METHOD_GLSL);
|
|
|
|
|
force_fallback |= (ibuf->dither != 0.0f);
|
|
|
|
|
|
|
|
|
|
/* Default */
|
|
|
|
|
*r_format = GPU_RGBA8;
|
|
|
|
|
*r_data = GPU_DATA_UBYTE;
|
|
|
|
|
|
|
|
|
|
/* Fallback to CPU based color space conversion. */
|
|
|
|
|
if (force_fallback) {
|
|
|
|
|
*r_glsl_used = false;
|
|
|
|
|
display_buffer = NULL;
|
|
|
|
|
}
|
|
|
|
|
else if (ibuf->rect_float) {
|
|
|
|
|
display_buffer = ibuf->rect_float;
|
|
|
|
|
|
|
|
|
|
*r_data = GPU_DATA_FLOAT;
|
|
|
|
|
if (ibuf->channels == 4) {
|
|
|
|
|
*r_format = GPU_RGBA16F;
|
|
|
|
|
}
|
|
|
|
|
else if (ibuf->channels == 3) {
|
|
|
|
|
/* Alpha is implicitly 1. */
|
|
|
|
|
*r_format = GPU_RGB16F;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ibuf->float_colorspace) {
|
|
|
|
|
*r_glsl_used = IMB_colormanagement_setup_glsl_draw_from_space(&ps->view_settings,
|
|
|
|
|
&ps->display_settings,
|
|
|
|
|
ibuf->float_colorspace,
|
|
|
|
|
ibuf->dither,
|
|
|
|
|
false,
|
|
|
|
|
false);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
*r_glsl_used = IMB_colormanagement_setup_glsl_draw(
|
|
|
|
|
&ps->view_settings, &ps->display_settings, ibuf->dither, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (ibuf->rect) {
|
|
|
|
|
display_buffer = ibuf->rect;
|
|
|
|
|
*r_glsl_used = IMB_colormanagement_setup_glsl_draw_from_space(&ps->view_settings,
|
|
|
|
|
&ps->display_settings,
|
2021-05-11 12:47:25 +02:00
|
|
|
ibuf->rect_colorspace,
|
2021-05-07 09:43:26 +02:00
|
|
|
ibuf->dither,
|
|
|
|
|
false,
|
|
|
|
|
false);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
display_buffer = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* There is data to be displayed, but GLSL is not initialized
|
|
|
|
|
* properly, in this case we fallback to CPU-based display transform. */
|
|
|
|
|
if ((ibuf->rect || ibuf->rect_float) && !*r_glsl_used) {
|
|
|
|
|
display_buffer = IMB_display_buffer_acquire(
|
|
|
|
|
ibuf, &ps->view_settings, &ps->display_settings, r_buffer_cache_handle);
|
|
|
|
|
*r_format = GPU_RGBA8;
|
|
|
|
|
*r_data = GPU_DATA_UBYTE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return display_buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void draw_display_buffer(PlayState *ps, ImBuf *ibuf)
|
|
|
|
|
{
|
|
|
|
|
void *display_buffer;
|
|
|
|
|
|
|
|
|
|
/* Format needs to be created prior to any #immBindShader call.
|
|
|
|
|
* Do it here because OCIO binds its own shader. */
|
|
|
|
|
eGPUTextureFormat format;
|
|
|
|
|
eGPUDataFormat data;
|
|
|
|
|
bool glsl_used = false;
|
|
|
|
|
GPUVertFormat *imm_format = immVertexFormat();
|
|
|
|
|
uint pos = GPU_vertformat_attr_add(imm_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
|
|
|
uint texCoord = GPU_vertformat_attr_add(
|
|
|
|
|
imm_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
|
|
|
|
|
|
|
|
void *buffer_cache_handle = NULL;
|
|
|
|
|
display_buffer = ocio_transform_ibuf(ps, ibuf, &glsl_used, &format, &data, &buffer_cache_handle);
|
|
|
|
|
|
|
|
|
|
GPUTexture *texture = GPU_texture_create_2d("display_buf", ibuf->x, ibuf->y, 1, format, NULL);
|
|
|
|
|
GPU_texture_update(texture, data, display_buffer);
|
|
|
|
|
GPU_texture_filter_mode(texture, false);
|
|
|
|
|
|
|
|
|
|
GPU_texture_bind(texture, 0);
|
|
|
|
|
|
|
|
|
|
if (!glsl_used) {
|
|
|
|
|
immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
|
|
|
|
|
immUniformColor3f(1.0f, 1.0f, 1.0f);
|
|
|
|
|
immUniform1i("image", 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
immBegin(GPU_PRIM_TRI_FAN, 4);
|
|
|
|
|
|
|
|
|
|
rctf preview;
|
|
|
|
|
rctf canvas;
|
|
|
|
|
|
|
|
|
|
BLI_rctf_init(&canvas, 0.0f, 1.0f, 0.0f, 1.0f);
|
|
|
|
|
BLI_rctf_init(&preview, 0.0f, 1.0f, 0.0f, 1.0f);
|
|
|
|
|
|
2021-05-08 14:27:28 +10:00
|
|
|
if (ps->draw_flip[0]) {
|
|
|
|
|
SWAP(float, canvas.xmin, canvas.xmax);
|
|
|
|
|
}
|
|
|
|
|
if (ps->draw_flip[1]) {
|
|
|
|
|
SWAP(float, canvas.ymin, canvas.ymax);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-07 09:43:26 +02:00
|
|
|
immAttr2f(texCoord, canvas.xmin, canvas.ymin);
|
|
|
|
|
immVertex2f(pos, preview.xmin, preview.ymin);
|
|
|
|
|
|
|
|
|
|
immAttr2f(texCoord, canvas.xmin, canvas.ymax);
|
|
|
|
|
immVertex2f(pos, preview.xmin, preview.ymax);
|
|
|
|
|
|
|
|
|
|
immAttr2f(texCoord, canvas.xmax, canvas.ymax);
|
|
|
|
|
immVertex2f(pos, preview.xmax, preview.ymax);
|
|
|
|
|
|
|
|
|
|
immAttr2f(texCoord, canvas.xmax, canvas.ymin);
|
|
|
|
|
immVertex2f(pos, preview.xmax, preview.ymin);
|
|
|
|
|
|
|
|
|
|
immEnd();
|
|
|
|
|
|
|
|
|
|
GPU_texture_unbind(texture);
|
|
|
|
|
GPU_texture_free(texture);
|
|
|
|
|
|
|
|
|
|
if (!glsl_used) {
|
|
|
|
|
immUnbindProgram();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
IMB_colormanagement_finish_glsl_draw();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (buffer_cache_handle) {
|
|
|
|
|
IMB_display_buffer_release(buffer_cache_handle);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-09 14:57:06 +00:00
|
|
|
static void playanim_toscreen(
|
|
|
|
|
PlayState *ps, PlayAnimPict *picture, struct ImBuf *ibuf, int fontid, int fstep)
|
2012-08-06 16:07:11 +00:00
|
|
|
{
|
|
|
|
|
if (ibuf == NULL) {
|
2012-11-17 01:15:28 +00:00
|
|
|
printf("%s: no ibuf for picture '%s'\n", __func__, picture ? picture->name : "<NIL>");
|
2012-08-06 16:07:11 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-10-01 21:59:02 +10:00
|
|
|
/* size within window */
|
2020-10-17 16:36:02 -05:00
|
|
|
float span_x = (ps->zoom * ibuf->x) / (float)ps->win_x;
|
|
|
|
|
float span_y = (ps->zoom * ibuf->y) / (float)ps->win_y;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-09 14:57:06 +00:00
|
|
|
/* offset within window */
|
2020-10-17 16:36:02 -05:00
|
|
|
float offs_x = 0.5f * (1.0f - span_x);
|
|
|
|
|
float offs_y = 0.5f * (1.0f - span_y);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-10-01 21:59:02 +10:00
|
|
|
CLAMP(offs_x, 0.0f, 1.0f);
|
|
|
|
|
CLAMP(offs_y, 0.0f, 1.0f);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-23 11:11:27 +02:00
|
|
|
GPU_clear_color(0.1f, 0.1f, 0.1f, 0.0f);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-09 14:57:06 +00:00
|
|
|
/* checkerboard for case alpha */
|
|
|
|
|
if (ibuf->planes == 32) {
|
2020-08-16 15:38:34 +02:00
|
|
|
GPU_blend(GPU_BLEND_ALPHA);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-30 17:45:02 +10:00
|
|
|
imm_draw_box_checker_2d_ex(offs_x,
|
|
|
|
|
offs_y,
|
|
|
|
|
offs_x + span_x,
|
|
|
|
|
offs_y + span_y,
|
|
|
|
|
(const float[4]){0.15, 0.15, 0.15, 1.0},
|
|
|
|
|
(const float[4]){0.20, 0.20, 0.20, 1.0},
|
|
|
|
|
8);
|
2013-03-09 14:57:06 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-05-07 09:43:26 +02:00
|
|
|
draw_display_buffer(ps, ibuf);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-16 15:38:34 +02:00
|
|
|
GPU_blend(GPU_BLEND_NONE);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
pupdate_time();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
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];
|
|
|
|
|
BLI_snprintf(str, sizeof(str), "%s | %.2f frames/s", picture->name, fstep / swaptime);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
playanim_window_get_size(&sizex, &sizey);
|
|
|
|
|
fsizex_inv = 1.0f / sizex;
|
|
|
|
|
fsizey_inv = 1.0f / sizey;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-04-11 01:21:15 +10:00
|
|
|
BLF_color4f(fontid, 1.0, 1.0, 1.0, 1.0);
|
2012-08-06 16:07:11 +00:00
|
|
|
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));
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-06-12 11:47:37 +02:00
|
|
|
if (ps->indicator) {
|
|
|
|
|
float fac = ps->picture->frame / (double)(((PlayAnimPict *)picsbase.last)->frame -
|
|
|
|
|
((PlayAnimPict *)picsbase.first)->frame);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-06-12 11:47:37 +02:00
|
|
|
fac = 2.0f * fac - 1.0f;
|
2018-07-15 15:27:15 +02:00
|
|
|
GPU_matrix_push_projection();
|
|
|
|
|
GPU_matrix_identity_projection_set();
|
|
|
|
|
GPU_matrix_push();
|
|
|
|
|
GPU_matrix_identity_set();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-18 00:12:21 +02:00
|
|
|
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-04-11 01:21:15 +10:00
|
|
|
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
|
2017-04-16 13:44:34 -04:00
|
|
|
immUniformColor3ub(0, 255, 0);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-18 00:12:21 +02:00
|
|
|
immBegin(GPU_PRIM_LINES, 2);
|
2017-04-11 01:21:15 +10:00
|
|
|
immVertex2f(pos, fac, -1.0f);
|
|
|
|
|
immVertex2f(pos, fac, 1.0f);
|
|
|
|
|
immEnd();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-04-11 01:21:15 +10:00
|
|
|
immUnbindProgram();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-15 15:27:15 +02:00
|
|
|
GPU_matrix_pop();
|
|
|
|
|
GPU_matrix_pop_projection();
|
2015-06-12 11:47:37 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
GHOST_SwapWindowBuffers(g_WS.ghost_window);
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-07 18:18:21 +10:00
|
|
|
static void build_pict_list_ex(
|
|
|
|
|
PlayState *ps, const char *first, int totframes, int fstep, int fontid)
|
2012-08-06 16:07:11 +00:00
|
|
|
{
|
|
|
|
|
if (IMB_isanim(first)) {
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
/* OCIO_TODO: support different input color space */
|
2020-10-17 16:36:02 -05:00
|
|
|
struct anim *anim = IMB_open_anim(first, IB_rect, 0, NULL);
|
2012-08-06 16:07:11 +00:00
|
|
|
if (anim) {
|
|
|
|
|
int pic;
|
2020-10-17 16:36:02 -05:00
|
|
|
struct ImBuf *ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
|
2012-08-06 16:07:11 +00:00
|
|
|
if (ibuf) {
|
2013-03-09 14:57:06 +00:00
|
|
|
playanim_toscreen(ps, NULL, ibuf, fontid, fstep);
|
2012-08-06 16:07:11 +00:00
|
|
|
IMB_freeImBuf(ibuf);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
for (pic = 0; pic < IMB_anim_get_duration(anim, IMB_TC_NONE); pic++) {
|
2020-10-17 16:36:02 -05:00
|
|
|
PlayAnimPict *picture = (PlayAnimPict *)MEM_callocN(sizeof(PlayAnimPict), "Pict");
|
2012-08-06 16:07:11 +00:00
|
|
|
picture->anim = anim;
|
|
|
|
|
picture->frame = pic;
|
|
|
|
|
picture->IB_flags = IB_rect;
|
2015-10-15 17:45:53 +11:00
|
|
|
picture->name = BLI_sprintfN("%s : %4.d", first, pic + 1);
|
2012-08-06 16:07:11 +00:00
|
|
|
BLI_addtail(&picsbase, picture);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
printf("couldn't open anim %s\n", first);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2021-05-07 17:54:52 +10:00
|
|
|
/* Load images into cache until the cache is full,
|
|
|
|
|
* this resolves choppiness for images that are slow to load, see: T81751. */
|
|
|
|
|
#ifdef USE_FRAME_CACHE_LIMIT
|
|
|
|
|
bool fill_cache = true;
|
|
|
|
|
#else
|
|
|
|
|
bool fill_cache = false;
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
int count = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-10-16 04:31:17 +11:00
|
|
|
int fp_framenr;
|
|
|
|
|
struct {
|
|
|
|
|
char head[FILE_MAX], tail[FILE_MAX];
|
|
|
|
|
unsigned short digits;
|
|
|
|
|
} fp_decoded;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-10-17 16:36:02 -05:00
|
|
|
char filepath[FILE_MAX];
|
2012-08-06 16:07:11 +00:00
|
|
|
BLI_strncpy(filepath, first, sizeof(filepath));
|
2020-04-07 12:02:21 +10:00
|
|
|
fp_framenr = BLI_path_sequence_decode(
|
|
|
|
|
filepath, fp_decoded.head, fp_decoded.tail, &fp_decoded.digits);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
pupdate_time();
|
|
|
|
|
ptottime = 1.0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
/* 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.
|
|
|
|
|
*/
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
while (IMB_ispic(filepath) && totframes) {
|
2021-05-07 17:12:41 +10:00
|
|
|
bool has_event;
|
2012-08-06 16:07:11 +00:00
|
|
|
size_t size;
|
|
|
|
|
int file;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-06-07 11:30:08 +10:00
|
|
|
file = BLI_open(filepath, O_BINARY | O_RDONLY, 0);
|
2012-09-13 01:50:21 +00:00
|
|
|
if (file < 0) {
|
|
|
|
|
/* print errno? */
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-10-17 16:36:02 -05:00
|
|
|
PlayAnimPict *picture = (PlayAnimPict *)MEM_callocN(sizeof(PlayAnimPict), "picture");
|
2012-08-06 16:07:11 +00:00
|
|
|
if (picture == NULL) {
|
|
|
|
|
printf("Not enough memory for pict struct '%s'\n", filepath);
|
|
|
|
|
close(file);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
size = BLI_file_descriptor_size(file);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
if (size < 1) {
|
|
|
|
|
close(file);
|
|
|
|
|
MEM_freeN(picture);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
picture->size = size;
|
|
|
|
|
picture->IB_flags = IB_rect;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-10-17 16:36:02 -05:00
|
|
|
uchar *mem;
|
2014-04-01 11:34:00 +11:00
|
|
|
if (fromdisk == false) {
|
2019-03-25 09:08:29 +11:00
|
|
|
mem = MEM_mallocN(size, "build pic list");
|
2012-08-06 16:07:11 +00:00
|
|
|
if (mem == NULL) {
|
|
|
|
|
printf("Couldn't get memory\n");
|
|
|
|
|
close(file);
|
|
|
|
|
MEM_freeN(picture);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
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;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
picture->mem = mem;
|
2015-10-15 17:45:53 +11:00
|
|
|
picture->name = BLI_strdup(filepath);
|
|
|
|
|
picture->frame = count;
|
2012-08-06 16:07:11 +00:00
|
|
|
close(file);
|
|
|
|
|
BLI_addtail(&picsbase, picture);
|
|
|
|
|
count++;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
pupdate_time();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-05-07 17:54:52 +10:00
|
|
|
const bool display_imbuf = ptottime > 1.0;
|
|
|
|
|
|
|
|
|
|
if (display_imbuf || fill_cache) {
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
/* OCIO_TODO: support different input color space */
|
2021-05-07 17:49:14 +10:00
|
|
|
ImBuf *ibuf = ibuf_from_picture(picture);
|
2021-05-07 17:54:52 +10:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
if (ibuf) {
|
2021-05-07 17:54:52 +10:00
|
|
|
if (display_imbuf) {
|
|
|
|
|
playanim_toscreen(ps, picture, ibuf, fontid, fstep);
|
|
|
|
|
}
|
|
|
|
|
#ifdef USE_FRAME_CACHE_LIMIT
|
|
|
|
|
if (fill_cache) {
|
|
|
|
|
picture->ibuf = ibuf;
|
|
|
|
|
frame_cache_add(picture);
|
|
|
|
|
fill_cache = !frame_cache_limit_exceeded();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
IMB_freeImBuf(ibuf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (display_imbuf) {
|
|
|
|
|
pupdate_time();
|
|
|
|
|
ptottime = 0.0;
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-10-16 04:31:17 +11:00
|
|
|
/* create a new filepath each time */
|
|
|
|
|
fp_framenr += fstep;
|
2020-04-07 12:02:21 +10:00
|
|
|
BLI_path_sequence_encode(
|
|
|
|
|
filepath, fp_decoded.head, fp_decoded.tail, fp_decoded.digits, fp_framenr);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-05-07 17:12:41 +10:00
|
|
|
while ((has_event = GHOST_ProcessEvents(g_WS.ghost_system, false))) {
|
2020-03-15 21:48:35 +11:00
|
|
|
GHOST_DispatchEvents(g_WS.ghost_system);
|
2014-05-07 18:18:21 +10:00
|
|
|
if (ps->loading == false) {
|
|
|
|
|
return;
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
totframes--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-07 18:18:21 +10:00
|
|
|
static void build_pict_list(PlayState *ps, const char *first, int totframes, int fstep, int fontid)
|
|
|
|
|
{
|
|
|
|
|
ps->loading = true;
|
|
|
|
|
build_pict_list_ex(ps, first, totframes, fstep, fontid);
|
|
|
|
|
ps->loading = false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-12 11:47:37 +02:00
|
|
|
static void update_sound_fps(void)
|
|
|
|
|
{
|
|
|
|
|
#ifdef WITH_AUDASPACE
|
|
|
|
|
if (playback_handle) {
|
|
|
|
|
/* swaptime stores the 1.0/fps ratio */
|
|
|
|
|
double speed = 1.0 / (swaptime * fps_movie);
|
|
|
|
|
|
2015-06-15 12:18:14 +02:00
|
|
|
AUD_Handle_setPitch(playback_handle, speed);
|
2015-06-12 11:47:37 +02:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-06 17:14:16 +02:00
|
|
|
static void tag_change_frame(PlayState *ps, int cx)
|
|
|
|
|
{
|
|
|
|
|
ps->need_frame_update = true;
|
|
|
|
|
ps->frame_cursor_x = cx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void change_frame(PlayState *ps)
|
2015-06-12 11:47:37 +02:00
|
|
|
{
|
2018-07-06 17:14:16 +02:00
|
|
|
if (!ps->need_frame_update) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-12 11:47:37 +02:00
|
|
|
int sizex, sizey;
|
2015-10-15 16:45:49 +11:00
|
|
|
int i, i_last;
|
2015-06-12 11:47:37 +02:00
|
|
|
|
2015-10-15 16:45:49 +11:00
|
|
|
if (BLI_listbase_is_empty(&picsbase)) {
|
|
|
|
|
return;
|
2015-06-12 11:47:37 +02:00
|
|
|
}
|
2015-10-15 16:45:49 +11:00
|
|
|
|
|
|
|
|
playanim_window_get_size(&sizex, &sizey);
|
|
|
|
|
i_last = ((struct PlayAnimPict *)picsbase.last)->frame;
|
2018-07-06 17:14:16 +02:00
|
|
|
i = (i_last * ps->frame_cursor_x) / sizex;
|
2015-10-15 16:45:49 +11:00
|
|
|
CLAMP(i, 0, i_last);
|
2015-06-12 11:47:37 +02:00
|
|
|
|
|
|
|
|
#ifdef WITH_AUDASPACE
|
|
|
|
|
if (scrub_handle) {
|
2015-06-15 12:18:14 +02:00
|
|
|
AUD_Handle_stop(scrub_handle);
|
2015-06-12 11:47:37 +02:00
|
|
|
scrub_handle = NULL;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-06-12 11:47:37 +02:00
|
|
|
if (playback_handle) {
|
2015-06-15 12:18:14 +02:00
|
|
|
AUD_Status status = AUD_Handle_getStatus(playback_handle);
|
2015-06-12 11:47:37 +02:00
|
|
|
if (status != AUD_STATUS_PLAYING) {
|
2015-06-15 12:18:14 +02:00
|
|
|
AUD_Handle_stop(playback_handle);
|
|
|
|
|
playback_handle = AUD_Device_play(audio_device, source, 1);
|
2015-06-12 11:47:37 +02:00
|
|
|
if (playback_handle) {
|
2015-06-15 12:18:14 +02:00
|
|
|
AUD_Handle_setPosition(playback_handle, i / fps_movie);
|
2015-06-12 11:47:37 +02:00
|
|
|
scrub_handle = AUD_pauseAfter(playback_handle, 1 / fps_movie);
|
|
|
|
|
}
|
|
|
|
|
update_sound_fps();
|
|
|
|
|
}
|
|
|
|
|
else {
|
2015-06-15 12:18:14 +02:00
|
|
|
AUD_Handle_setPosition(playback_handle, i / fps_movie);
|
2015-06-12 11:47:37 +02:00
|
|
|
scrub_handle = AUD_pauseAfter(playback_handle, 1 / fps_movie);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (source) {
|
2015-06-15 12:18:14 +02:00
|
|
|
playback_handle = AUD_Device_play(audio_device, source, 1);
|
2015-06-12 11:47:37 +02:00
|
|
|
if (playback_handle) {
|
2015-06-15 12:18:14 +02:00
|
|
|
AUD_Handle_setPosition(playback_handle, i / fps_movie);
|
2015-06-12 11:47:37 +02:00
|
|
|
scrub_handle = AUD_pauseAfter(playback_handle, 1 / fps_movie);
|
|
|
|
|
}
|
|
|
|
|
update_sound_fps();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2015-10-15 16:45:49 +11:00
|
|
|
ps->picture = BLI_findlink(&picsbase, i);
|
|
|
|
|
BLI_assert(ps->picture != NULL);
|
2015-06-12 11:47:37 +02:00
|
|
|
|
|
|
|
|
ps->sstep = true;
|
|
|
|
|
ps->wait2 = false;
|
|
|
|
|
ps->next_frame = 0;
|
2018-07-06 17:14:16 +02:00
|
|
|
|
|
|
|
|
ps->need_frame_update = false;
|
2015-06-12 11:47:37 +02:00
|
|
|
}
|
|
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
|
|
|
|
|
{
|
|
|
|
|
PlayState *ps = (PlayState *)ps_void;
|
2021-05-08 15:50:34 +10:00
|
|
|
const GHOST_TEventType type = GHOST_GetEventType(evt);
|
|
|
|
|
/* Convert ghost event into value keyboard or mouse. */
|
|
|
|
|
const int val = ELEM(type, GHOST_kEventKeyDown, GHOST_kEventButtonDown);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
// print_ps(ps);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
playanim_event_qual_update();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-05-07 18:18:21 +10:00
|
|
|
/* first check if we're busy loading files */
|
|
|
|
|
if (ps->loading) {
|
|
|
|
|
switch (type) {
|
|
|
|
|
case GHOST_kEventKeyDown:
|
|
|
|
|
case GHOST_kEventKeyUp: {
|
|
|
|
|
GHOST_TEventKeyData *key_data;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-05-07 18:18:21 +10:00
|
|
|
key_data = (GHOST_TEventKeyData *)GHOST_GetEventData(evt);
|
|
|
|
|
switch (key_data->key) {
|
|
|
|
|
case GHOST_kKeyEsc:
|
|
|
|
|
ps->loading = false;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-05-09 18:29:21 +10:00
|
|
|
break;
|
2014-05-07 18:18:21 +10:00
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-05-08 15:57:57 +10:00
|
|
|
if (ps->wait2 && ps->stopped == false) {
|
|
|
|
|
ps->stopped = true;
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-11-17 04:47:33 +00:00
|
|
|
if (ps->wait2) {
|
|
|
|
|
pupdate_time();
|
|
|
|
|
ptottime = 0;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
switch (type) {
|
|
|
|
|
case GHOST_kEventKeyDown:
|
|
|
|
|
case GHOST_kEventKeyUp: {
|
|
|
|
|
GHOST_TEventKeyData *key_data;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
key_data = (GHOST_TEventKeyData *)GHOST_GetEventData(evt);
|
|
|
|
|
switch (key_data->key) {
|
|
|
|
|
case GHOST_kKeyA:
|
2019-04-13 09:15:15 +02:00
|
|
|
if (val) {
|
|
|
|
|
ps->noskip = !ps->noskip;
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
break;
|
2015-06-12 11:47:37 +02:00
|
|
|
case GHOST_kKeyI:
|
2019-04-13 09:15:15 +02:00
|
|
|
if (val) {
|
|
|
|
|
ps->indicator = !ps->indicator;
|
|
|
|
|
}
|
2015-06-12 11:47:37 +02:00
|
|
|
break;
|
2012-08-06 16:07:11 +00:00
|
|
|
case GHOST_kKeyP:
|
2019-04-13 09:15:15 +02:00
|
|
|
if (val) {
|
|
|
|
|
ps->pingpong = !ps->pingpong;
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
break;
|
2014-10-01 21:59:02 +10:00
|
|
|
case GHOST_kKeyF: {
|
|
|
|
|
if (val) {
|
|
|
|
|
int axis = (g_WS.qual & WS_QUAL_SHIFT) ? 1 : 0;
|
|
|
|
|
ps->draw_flip[axis] = !ps->draw_flip[axis];
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-11-21 03:33:49 +00:00
|
|
|
case GHOST_kKey1:
|
2012-08-06 16:07:11 +00:00
|
|
|
case GHOST_kKeyNumpad1:
|
2015-06-12 11:47:37 +02:00
|
|
|
if (val) {
|
|
|
|
|
swaptime = ps->fstep / 60.0;
|
|
|
|
|
update_sound_fps();
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
break;
|
2012-11-21 03:33:49 +00:00
|
|
|
case GHOST_kKey2:
|
2012-08-06 16:07:11 +00:00
|
|
|
case GHOST_kKeyNumpad2:
|
2015-06-12 11:47:37 +02:00
|
|
|
if (val) {
|
|
|
|
|
swaptime = ps->fstep / 50.0;
|
|
|
|
|
update_sound_fps();
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
break;
|
2012-11-21 03:33:49 +00:00
|
|
|
case GHOST_kKey3:
|
2012-08-06 16:07:11 +00:00
|
|
|
case GHOST_kKeyNumpad3:
|
2015-06-12 11:47:37 +02:00
|
|
|
if (val) {
|
|
|
|
|
swaptime = ps->fstep / 30.0;
|
|
|
|
|
update_sound_fps();
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
break;
|
2012-11-21 03:33:49 +00:00
|
|
|
case GHOST_kKey4:
|
2012-08-06 16:07:11 +00:00
|
|
|
case GHOST_kKeyNumpad4:
|
2015-06-12 11:47:37 +02:00
|
|
|
if (g_WS.qual & WS_QUAL_SHIFT) {
|
2012-10-12 14:03:43 +00:00
|
|
|
swaptime = ps->fstep / 24.0;
|
2015-06-12 11:47:37 +02:00
|
|
|
update_sound_fps();
|
|
|
|
|
}
|
|
|
|
|
else {
|
2012-10-12 14:03:43 +00:00
|
|
|
swaptime = ps->fstep / 25.0;
|
2015-06-12 11:47:37 +02:00
|
|
|
update_sound_fps();
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
break;
|
2012-11-21 03:33:49 +00:00
|
|
|
case GHOST_kKey5:
|
2012-08-06 16:07:11 +00:00
|
|
|
case GHOST_kKeyNumpad5:
|
2015-06-12 11:47:37 +02:00
|
|
|
if (val) {
|
|
|
|
|
swaptime = ps->fstep / 20.0;
|
|
|
|
|
update_sound_fps();
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
break;
|
2012-11-21 03:33:49 +00:00
|
|
|
case GHOST_kKey6:
|
2012-08-06 16:07:11 +00:00
|
|
|
case GHOST_kKeyNumpad6:
|
2015-06-12 11:47:37 +02:00
|
|
|
if (val) {
|
|
|
|
|
swaptime = ps->fstep / 15.0;
|
|
|
|
|
update_sound_fps();
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
break;
|
2012-11-21 03:33:49 +00:00
|
|
|
case GHOST_kKey7:
|
2012-08-06 16:07:11 +00:00
|
|
|
case GHOST_kKeyNumpad7:
|
2015-06-12 11:47:37 +02:00
|
|
|
if (val) {
|
|
|
|
|
swaptime = ps->fstep / 12.0;
|
|
|
|
|
update_sound_fps();
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
break;
|
2012-11-21 03:33:49 +00:00
|
|
|
case GHOST_kKey8:
|
2012-08-06 16:07:11 +00:00
|
|
|
case GHOST_kKeyNumpad8:
|
2015-06-12 11:47:37 +02:00
|
|
|
if (val) {
|
|
|
|
|
swaptime = ps->fstep / 10.0;
|
|
|
|
|
update_sound_fps();
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
break;
|
2012-11-21 03:33:49 +00:00
|
|
|
case GHOST_kKey9:
|
2012-08-06 16:07:11 +00:00
|
|
|
case GHOST_kKeyNumpad9:
|
2015-06-12 11:47:37 +02:00
|
|
|
if (val) {
|
|
|
|
|
swaptime = ps->fstep / 6.0;
|
|
|
|
|
update_sound_fps();
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
break;
|
|
|
|
|
case GHOST_kKeyLeftArrow:
|
|
|
|
|
if (val) {
|
2014-04-01 11:34:00 +11:00
|
|
|
ps->sstep = true;
|
|
|
|
|
ps->wait2 = false;
|
2012-08-06 16:07:11 +00:00
|
|
|
if (g_WS.qual & WS_QUAL_SHIFT) {
|
|
|
|
|
ps->picture = picsbase.first;
|
2012-12-06 06:01:15 +00:00
|
|
|
ps->next_frame = 0;
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-12-06 06:01:15 +00:00
|
|
|
ps->next_frame = -1;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case GHOST_kKeyDownArrow:
|
|
|
|
|
if (val) {
|
2014-04-01 11:34:00 +11:00
|
|
|
ps->wait2 = false;
|
2012-08-06 16:07:11 +00:00
|
|
|
if (g_WS.qual & WS_QUAL_SHIFT) {
|
2012-12-06 06:01:15 +00:00
|
|
|
ps->next_frame = ps->direction = -1;
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-12-06 06:01:15 +00:00
|
|
|
ps->next_frame = -10;
|
2014-04-01 11:34:00 +11:00
|
|
|
ps->sstep = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case GHOST_kKeyRightArrow:
|
|
|
|
|
if (val) {
|
2014-04-01 11:34:00 +11:00
|
|
|
ps->sstep = true;
|
|
|
|
|
ps->wait2 = false;
|
2012-08-06 16:07:11 +00:00
|
|
|
if (g_WS.qual & WS_QUAL_SHIFT) {
|
|
|
|
|
ps->picture = picsbase.last;
|
2012-12-06 06:01:15 +00:00
|
|
|
ps->next_frame = 0;
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-12-06 06:01:15 +00:00
|
|
|
ps->next_frame = 1;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case GHOST_kKeyUpArrow:
|
|
|
|
|
if (val) {
|
2014-04-01 11:34:00 +11:00
|
|
|
ps->wait2 = false;
|
2012-08-06 16:07:11 +00:00
|
|
|
if (g_WS.qual & WS_QUAL_SHIFT) {
|
2012-12-06 06:01:15 +00:00
|
|
|
ps->next_frame = ps->direction = 1;
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-12-06 06:01:15 +00:00
|
|
|
ps->next_frame = 10;
|
2014-04-01 11:34:00 +11:00
|
|
|
ps->sstep = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
case GHOST_kKeySlash:
|
|
|
|
|
case GHOST_kKeyNumpadSlash:
|
|
|
|
|
if (val) {
|
|
|
|
|
if (g_WS.qual & WS_QUAL_SHIFT) {
|
2021-05-07 17:25:06 +10:00
|
|
|
if (ps->picture && ps->picture->ibuf) {
|
2012-12-06 06:01:15 +00:00
|
|
|
printf(" Name: %s | Speed: %.2f frames/s\n",
|
2021-05-07 17:25:06 +10:00
|
|
|
ps->picture->ibuf->name,
|
2012-12-06 06:01:15 +00:00
|
|
|
ps->fstep / swaptime);
|
2019-04-13 09:15:15 +02:00
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-10-12 14:03:43 +00:00
|
|
|
swaptime = ps->fstep / 5.0;
|
2015-06-12 11:47:37 +02:00
|
|
|
update_sound_fps();
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
2012-11-21 03:33:49 +00:00
|
|
|
case GHOST_kKey0:
|
2012-08-06 16:07:11 +00:00
|
|
|
case GHOST_kKeyNumpad0:
|
|
|
|
|
if (val) {
|
|
|
|
|
if (ps->once) {
|
2014-04-01 11:34:00 +11:00
|
|
|
ps->once = ps->wait2 = false;
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
ps->picture = NULL;
|
2014-04-01 11:34:00 +11:00
|
|
|
ps->once = true;
|
|
|
|
|
ps->wait2 = false;
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-06-12 11:47:37 +02:00
|
|
|
case GHOST_kKeySpace:
|
|
|
|
|
if (val) {
|
|
|
|
|
if (ps->wait2 || ps->sstep) {
|
|
|
|
|
ps->wait2 = ps->sstep = false;
|
|
|
|
|
#ifdef WITH_AUDASPACE
|
|
|
|
|
{
|
|
|
|
|
PlayAnimPict *picture = picsbase.first;
|
|
|
|
|
/* TODO - store in ps direct? */
|
|
|
|
|
int i = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-06-12 11:47:37 +02:00
|
|
|
while (picture && picture != ps->picture) {
|
|
|
|
|
i++;
|
|
|
|
|
picture = picture->next;
|
|
|
|
|
}
|
2019-04-13 09:15:15 +02:00
|
|
|
if (playback_handle) {
|
2015-06-15 12:18:14 +02:00
|
|
|
AUD_Handle_stop(playback_handle);
|
2019-04-13 09:15:15 +02:00
|
|
|
}
|
2015-06-15 12:18:14 +02:00
|
|
|
playback_handle = AUD_Device_play(audio_device, source, 1);
|
2019-04-13 09:15:15 +02:00
|
|
|
if (playback_handle) {
|
2015-06-15 12:18:14 +02:00
|
|
|
AUD_Handle_setPosition(playback_handle, i / fps_movie);
|
2019-04-13 09:15:15 +02:00
|
|
|
}
|
2015-06-12 11:47:37 +02:00
|
|
|
update_sound_fps();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
ps->sstep = true;
|
|
|
|
|
ps->wait2 = true;
|
|
|
|
|
#ifdef WITH_AUDASPACE
|
|
|
|
|
if (playback_handle) {
|
2015-06-15 12:18:14 +02:00
|
|
|
AUD_Handle_stop(playback_handle);
|
2015-06-12 11:47:37 +02:00
|
|
|
playback_handle = NULL;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
2012-08-06 16:07:11 +00:00
|
|
|
case GHOST_kKeyEnter:
|
|
|
|
|
case GHOST_kKeyNumpadEnter:
|
|
|
|
|
if (val) {
|
2014-04-01 11:34:00 +11:00
|
|
|
ps->wait2 = ps->sstep = false;
|
2015-06-12 11:47:37 +02:00
|
|
|
#ifdef WITH_AUDASPACE
|
|
|
|
|
{
|
|
|
|
|
PlayAnimPict *picture = picsbase.first;
|
|
|
|
|
/* TODO - store in ps direct? */
|
|
|
|
|
int i = 0;
|
|
|
|
|
while (picture && picture != ps->picture) {
|
|
|
|
|
i++;
|
|
|
|
|
picture = picture->next;
|
|
|
|
|
}
|
2019-04-13 09:15:15 +02:00
|
|
|
if (playback_handle) {
|
2015-06-15 12:18:14 +02:00
|
|
|
AUD_Handle_stop(playback_handle);
|
2019-04-13 09:15:15 +02:00
|
|
|
}
|
2015-06-15 12:18:14 +02:00
|
|
|
playback_handle = AUD_Device_play(audio_device, source, 1);
|
2019-04-13 09:15:15 +02:00
|
|
|
if (playback_handle) {
|
2015-06-15 12:18:14 +02:00
|
|
|
AUD_Handle_setPosition(playback_handle, i / fps_movie);
|
2019-04-13 09:15:15 +02:00
|
|
|
}
|
2015-06-12 11:47:37 +02:00
|
|
|
update_sound_fps();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
break;
|
2012-11-21 03:33:49 +00:00
|
|
|
case GHOST_kKeyPeriod:
|
2012-08-06 16:07:11 +00:00
|
|
|
case GHOST_kKeyNumpadPeriod:
|
|
|
|
|
if (val) {
|
2013-03-09 03:46:30 +00:00
|
|
|
if (ps->sstep) {
|
2014-04-01 11:34:00 +11:00
|
|
|
ps->wait2 = false;
|
2013-03-09 03:46:30 +00:00
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
else {
|
2014-04-01 11:34:00 +11:00
|
|
|
ps->sstep = true;
|
2012-08-06 16:07:11 +00:00
|
|
|
ps->wait2 = !ps->wait2;
|
2015-06-12 11:47:37 +02:00
|
|
|
#ifdef WITH_AUDASPACE
|
|
|
|
|
if (playback_handle) {
|
2015-06-15 12:18:14 +02:00
|
|
|
AUD_Handle_stop(playback_handle);
|
2015-06-12 11:47:37 +02:00
|
|
|
playback_handle = NULL;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
2012-11-17 06:32:35 +00:00
|
|
|
case GHOST_kKeyEqual:
|
2016-05-10 08:22:40 +02:00
|
|
|
case GHOST_kKeyPlus:
|
2012-08-06 16:07:11 +00:00
|
|
|
case GHOST_kKeyNumpadPlus: {
|
2019-04-13 09:15:15 +02:00
|
|
|
if (val == 0) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-11-17 06:32:35 +00:00
|
|
|
if (g_WS.qual & WS_QUAL_CTRL) {
|
2019-01-24 15:07:53 +01:00
|
|
|
playanim_window_zoom(ps, 0.1f);
|
2012-11-17 06:32:35 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2015-06-12 11:47:37 +02:00
|
|
|
if (swaptime > ps->fstep / 60.0) {
|
|
|
|
|
swaptime /= 1.1;
|
|
|
|
|
update_sound_fps();
|
|
|
|
|
}
|
2012-11-17 06:32:35 +00:00
|
|
|
}
|
2012-11-17 06:05:37 +00:00
|
|
|
break;
|
2012-11-17 06:32:35 +00:00
|
|
|
}
|
|
|
|
|
case GHOST_kKeyMinus:
|
2012-08-06 16:07:11 +00:00
|
|
|
case GHOST_kKeyNumpadMinus: {
|
2019-04-13 09:15:15 +02:00
|
|
|
if (val == 0) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-11-17 06:32:35 +00:00
|
|
|
if (g_WS.qual & WS_QUAL_CTRL) {
|
2019-01-24 15:07:53 +01:00
|
|
|
playanim_window_zoom(ps, -0.1f);
|
2012-11-17 06:32:35 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2015-06-12 11:47:37 +02:00
|
|
|
if (swaptime < ps->fstep / 5.0) {
|
|
|
|
|
swaptime *= 1.1;
|
|
|
|
|
update_sound_fps();
|
|
|
|
|
}
|
2012-11-17 06:32:35 +00:00
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case GHOST_kKeyEsc:
|
2014-04-01 11:34:00 +11:00
|
|
|
ps->go = false;
|
2012-08-06 16:07:11 +00:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-11-21 03:33:49 +00:00
|
|
|
case GHOST_kEventButtonDown:
|
|
|
|
|
case GHOST_kEventButtonUp: {
|
|
|
|
|
GHOST_TEventButtonData *bd = GHOST_GetEventData(evt);
|
|
|
|
|
int cx, cy, sizex, sizey, inside_window;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-11-21 03:33:49 +00:00
|
|
|
GHOST_GetCursorPosition(g_WS.ghost_system, &cx, &cy);
|
|
|
|
|
GHOST_ScreenToClient(g_WS.ghost_window, cx, cy, &cx, &cy);
|
|
|
|
|
playanim_window_get_size(&sizex, &sizey);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-11-21 03:33:49 +00:00
|
|
|
inside_window = (cx >= 0 && cx < sizex && cy >= 0 && cy <= sizey);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-11-21 03:33:49 +00:00
|
|
|
if (bd->button == GHOST_kButtonMaskLeft) {
|
|
|
|
|
if (type == GHOST_kEventButtonDown) {
|
2015-06-12 11:47:37 +02:00
|
|
|
if (inside_window) {
|
2012-11-21 03:33:49 +00:00
|
|
|
g_WS.qual |= WS_QUAL_LMOUSE;
|
2018-07-06 17:14:16 +02:00
|
|
|
tag_change_frame(ps, cx);
|
2015-06-12 11:47:37 +02:00
|
|
|
}
|
2012-11-21 03:33:49 +00:00
|
|
|
}
|
2019-04-13 09:15:15 +02:00
|
|
|
else {
|
2012-11-21 03:33:49 +00:00
|
|
|
g_WS.qual &= ~WS_QUAL_LMOUSE;
|
2019-04-13 09:15:15 +02:00
|
|
|
}
|
2012-11-21 03:33:49 +00:00
|
|
|
}
|
|
|
|
|
else if (bd->button == GHOST_kButtonMaskMiddle) {
|
|
|
|
|
if (type == GHOST_kEventButtonDown) {
|
2019-04-13 09:15:15 +02:00
|
|
|
if (inside_window) {
|
2012-11-21 03:33:49 +00:00
|
|
|
g_WS.qual |= WS_QUAL_MMOUSE;
|
2019-04-13 09:15:15 +02:00
|
|
|
}
|
2012-11-21 03:33:49 +00:00
|
|
|
}
|
2019-04-13 09:15:15 +02:00
|
|
|
else {
|
2012-11-21 03:33:49 +00:00
|
|
|
g_WS.qual &= ~WS_QUAL_MMOUSE;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-11-21 03:33:49 +00:00
|
|
|
else if (bd->button == GHOST_kButtonMaskRight) {
|
|
|
|
|
if (type == GHOST_kEventButtonDown) {
|
2019-04-13 09:15:15 +02:00
|
|
|
if (inside_window) {
|
2012-11-21 03:33:49 +00:00
|
|
|
g_WS.qual |= WS_QUAL_RMOUSE;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-04-13 09:15:15 +02:00
|
|
|
else {
|
2012-11-21 03:33:49 +00:00
|
|
|
g_WS.qual &= ~WS_QUAL_RMOUSE;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-11-21 03:33:49 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
case GHOST_kEventCursorMove: {
|
|
|
|
|
if (g_WS.qual & WS_QUAL_LMOUSE) {
|
|
|
|
|
GHOST_TEventCursorData *cd = GHOST_GetEventData(evt);
|
|
|
|
|
int cx, cy;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-10-15 17:25:43 +11:00
|
|
|
/* Ignore 'in-between' events, since they can make scrubbing lag.
|
|
|
|
|
*
|
|
|
|
|
* Ideally we would keep into the event queue and see if this is the last motion event.
|
|
|
|
|
* however the API currently doesn't support this. */
|
|
|
|
|
{
|
|
|
|
|
int x_test, y_test;
|
|
|
|
|
GHOST_GetCursorPosition(g_WS.ghost_system, &x_test, &y_test);
|
|
|
|
|
if (x_test != cd->x || y_test != cd->y) {
|
|
|
|
|
/* we're not the last event... skipping */
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
GHOST_ScreenToClient(g_WS.ghost_window, cd->x, cd->y, &cx, &cy);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-06 17:14:16 +02:00
|
|
|
tag_change_frame(ps, cx);
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-11-21 03:33:49 +00:00
|
|
|
case GHOST_kEventWindowActivate:
|
2013-01-15 23:45:41 +00:00
|
|
|
case GHOST_kEventWindowDeactivate: {
|
2012-11-21 03:33:49 +00:00
|
|
|
g_WS.qual &= ~WS_QUAL_MOUSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
case GHOST_kEventWindowSize:
|
|
|
|
|
case GHOST_kEventWindowMove: {
|
2013-03-09 14:57:06 +00:00
|
|
|
float zoomx, zoomy;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-09 14:57:06 +00:00
|
|
|
playanim_window_get_size(&ps->win_x, &ps->win_y);
|
2012-08-06 16:07:11 +00:00
|
|
|
GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-09 14:57:06 +00:00
|
|
|
zoomx = (float)ps->win_x / ps->ibufx;
|
|
|
|
|
zoomy = (float)ps->win_y / ps->ibufy;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-09 14:57:06 +00:00
|
|
|
/* zoom always show entire image */
|
|
|
|
|
ps->zoom = MIN2(zoomx, zoomy);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-07-17 19:03:30 +02:00
|
|
|
GPU_viewport(0, 0, ps->win_x, ps->win_y);
|
2020-07-17 19:13:43 +02:00
|
|
|
GPU_scissor(0, 0, ps->win_x, ps->win_y);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-10-01 20:45:05 +10:00
|
|
|
playanim_gl_matrix();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
ptottime = 0.0;
|
2021-05-07 17:25:06 +10:00
|
|
|
playanim_toscreen(
|
|
|
|
|
ps, ps->picture, ps->picture ? ps->picture->ibuf : NULL, ps->fontid, ps->fstep);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2019-05-18 00:12:21 +02:00
|
|
|
case GHOST_kEventQuitRequest:
|
2012-08-06 16:07:11 +00:00
|
|
|
case GHOST_kEventWindowClose: {
|
2014-04-01 11:34:00 +11:00
|
|
|
ps->go = false;
|
2012-08-06 16:07:11 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2013-03-08 13:03:04 +00:00
|
|
|
case GHOST_kEventDraggingDropDone: {
|
|
|
|
|
GHOST_TEventDragnDropData *ddd = GHOST_GetEventData(evt);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-08 13:03:04 +00:00
|
|
|
if (ddd->dataType == GHOST_kDragnDropTypeFilenames) {
|
|
|
|
|
GHOST_TStringArray *stra = ddd->data;
|
|
|
|
|
int a;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-08 13:03:04 +00:00
|
|
|
for (a = 0; a < stra->count; a++) {
|
|
|
|
|
BLI_strncpy(ps->dropped_file, (char *)stra->strings[a], sizeof(ps->dropped_file));
|
2014-04-01 11:34:00 +11:00
|
|
|
ps->go = false;
|
2013-03-08 13:03:04 +00:00
|
|
|
printf("drop file %s\n", stra->strings[a]);
|
|
|
|
|
break; /* only one drop element supported now */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
default:
|
|
|
|
|
/* quiet warnings */
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-28 01:15:59 +00:00
|
|
|
static void playanim_window_open(const char *title, int posx, int posy, int sizex, int sizey)
|
2012-08-06 16:07:11 +00:00
|
|
|
{
|
2015-02-25 13:51:53 +01:00
|
|
|
GHOST_GLSettings glsettings = {0};
|
2012-08-06 16:07:11 +00:00
|
|
|
GHOST_TUns32 scr_w, scr_h;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &scr_w, &scr_h);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
posy = (scr_h - posy - sizey);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
g_WS.ghost_window = GHOST_CreateWindow(g_WS.ghost_system,
|
2021-02-09 16:14:31 -08:00
|
|
|
NULL,
|
2012-09-13 01:50:21 +00:00
|
|
|
title,
|
|
|
|
|
posx,
|
|
|
|
|
posy,
|
|
|
|
|
sizex,
|
|
|
|
|
sizey,
|
2013-05-28 01:15:59 +00:00
|
|
|
/* could optionally start fullscreen */
|
|
|
|
|
GHOST_kWindowStateNormal,
|
2021-02-09 16:14:31 -08:00
|
|
|
false,
|
2012-09-13 01:50:21 +00:00
|
|
|
GHOST_kDrawingContextTypeOpenGL,
|
2015-02-25 13:51:53 +01:00
|
|
|
glsettings);
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-09 14:57:06 +00:00
|
|
|
static void playanim_window_zoom(PlayState *ps, const float zoom_offset)
|
2012-11-17 06:05:37 +00:00
|
|
|
{
|
|
|
|
|
int sizex, sizey;
|
|
|
|
|
/* int ofsx, ofsy; */ /* UNUSED */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-13 09:15:15 +02:00
|
|
|
if (ps->zoom + zoom_offset > 0.0f) {
|
|
|
|
|
ps->zoom += zoom_offset;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-11-17 06:05:37 +00:00
|
|
|
// playanim_window_get_position(&ofsx, &ofsy);
|
|
|
|
|
playanim_window_get_size(&sizex, &sizey);
|
|
|
|
|
/* ofsx += sizex / 2; */ /* UNUSED */
|
|
|
|
|
/* ofsy += sizey / 2; */ /* UNUSED */
|
2013-03-09 14:57:06 +00:00
|
|
|
sizex = ps->zoom * ps->ibufx;
|
|
|
|
|
sizey = ps->zoom * ps->ibufy;
|
2012-11-17 06:05:37 +00:00
|
|
|
/* ofsx -= sizex / 2; */ /* UNUSED */
|
|
|
|
|
/* ofsy -= sizey / 2; */ /* UNUSED */
|
2013-03-18 18:25:05 +00:00
|
|
|
// window_set_position(g_WS.ghost_window, sizex, sizey);
|
2012-11-17 06:05:37 +00:00
|
|
|
GHOST_SetClientSize(g_WS.ghost_window, sizex, sizey);
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
|
2021-05-10 15:30:20 +10:00
|
|
|
/**
|
|
|
|
|
* \return The a path used to restart the animation player or NULL to exit.
|
|
|
|
|
*/
|
2013-03-08 13:03:04 +00:00
|
|
|
static char *wm_main_playanim_intern(int argc, const char **argv)
|
2012-08-06 16:07:11 +00:00
|
|
|
{
|
|
|
|
|
struct ImBuf *ibuf = NULL;
|
2013-03-08 13:03:04 +00:00
|
|
|
static char filepath[FILE_MAX]; /* abused to return dropped file path */
|
2012-08-06 16:07:11 +00:00
|
|
|
GHOST_TUns32 maxwinx, maxwiny;
|
|
|
|
|
int i;
|
|
|
|
|
/* This was done to disambiguate the name for use under c++. */
|
|
|
|
|
int start_x = 0, start_y = 0;
|
|
|
|
|
int sfra = -1;
|
|
|
|
|
int efra = -1;
|
|
|
|
|
int totblock;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
PlayState ps = {0};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-04-01 11:34:00 +11:00
|
|
|
ps.go = true;
|
|
|
|
|
ps.direction = true;
|
2012-12-06 06:01:15 +00:00
|
|
|
ps.next_frame = 1;
|
2014-04-01 11:34:00 +11:00
|
|
|
ps.once = false;
|
|
|
|
|
ps.pingpong = false;
|
|
|
|
|
ps.noskip = false;
|
|
|
|
|
ps.sstep = false;
|
|
|
|
|
ps.wait2 = false;
|
|
|
|
|
ps.stopped = false;
|
2014-05-07 18:18:21 +10:00
|
|
|
ps.loading = false;
|
2012-08-06 16:07:11 +00:00
|
|
|
ps.picture = NULL;
|
2015-06-12 11:47:37 +02:00
|
|
|
ps.indicator = false;
|
2013-03-08 13:03:04 +00:00
|
|
|
ps.dropped_file[0] = 0;
|
2013-03-09 14:57:06 +00:00
|
|
|
ps.zoom = 1.0f;
|
2014-10-01 21:59:02 +10:00
|
|
|
ps.draw_flip[0] = false;
|
|
|
|
|
ps.draw_flip[1] = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-10-12 14:03:43 +00:00
|
|
|
ps.fstep = 1;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
ps.fontid = -1;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-05-07 09:43:26 +02:00
|
|
|
STRNCPY(ps.display_settings.display_device,
|
|
|
|
|
IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_BYTE));
|
|
|
|
|
IMB_colormanagement_init_default_view_settings(&ps.view_settings, &ps.display_settings);
|
|
|
|
|
|
2021-05-10 15:30:20 +10:00
|
|
|
/* Skip the first argument which is assumed to be '-a' (used to launch this player). */
|
2012-08-06 16:07:11 +00:00
|
|
|
while (argc > 1) {
|
|
|
|
|
if (argv[1][0] == '-') {
|
|
|
|
|
switch (argv[1][1]) {
|
|
|
|
|
case 'm':
|
2014-04-01 11:34:00 +11:00
|
|
|
fromdisk = true;
|
2012-08-06 16:07:11 +00:00
|
|
|
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':
|
2013-11-29 13:59:32 +11:00
|
|
|
sfra = atoi(argv[2]);
|
|
|
|
|
CLAMP(sfra, 1, MAXFRAME);
|
2012-08-06 16:07:11 +00:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
|
|
|
|
break;
|
|
|
|
|
case 'e':
|
2013-11-29 13:59:32 +11:00
|
|
|
efra = atoi(argv[2]);
|
|
|
|
|
CLAMP(efra, 1, MAXFRAME);
|
2012-08-06 16:07:11 +00:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
|
|
|
|
break;
|
|
|
|
|
case 'j':
|
2013-11-29 13:59:32 +11:00
|
|
|
ps.fstep = atoi(argv[2]);
|
|
|
|
|
CLAMP(ps.fstep, 1, MAXFRAME);
|
2012-10-12 14:03:43 +00:00
|
|
|
swaptime *= ps.fstep;
|
2012-08-06 16:07:11 +00:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
|
|
|
|
break;
|
2021-05-06 11:22:54 +10:00
|
|
|
case 'c': {
|
|
|
|
|
#ifdef USE_FRAME_CACHE_LIMIT
|
|
|
|
|
const int memory_in_mb = max_ii(0, atoi(argv[2]));
|
2021-05-07 17:12:41 +10:00
|
|
|
g_frame_cache.memory_limit = (size_t)memory_in_mb * (1024 * 1024);
|
2021-05-06 11:22:54 +10:00
|
|
|
#endif
|
|
|
|
|
argc--;
|
|
|
|
|
argv++;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
default:
|
|
|
|
|
printf("unknown option '%c': skipping\n", argv[1][1]);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
argc--;
|
|
|
|
|
argv++;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
if (argc > 1) {
|
|
|
|
|
BLI_strncpy(filepath, argv[1], sizeof(filepath));
|
|
|
|
|
}
|
|
|
|
|
else {
|
2015-10-08 14:42:25 +11:00
|
|
|
printf("%s: no filepath argument given\n", __func__);
|
|
|
|
|
exit(1);
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
if (IMB_isanim(filepath)) {
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
/* OCIO_TODO: support different input color spaces */
|
2015-10-15 17:45:53 +11:00
|
|
|
struct anim *anim;
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
anim = IMB_open_anim(filepath, IB_rect, 0, NULL);
|
2012-08-06 16:07:11 +00:00
|
|
|
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)) {
|
2013-07-13 12:58:00 +00:00
|
|
|
printf("%s: '%s' not an image file\n", __func__, filepath);
|
2012-08-06 16:07:11 +00:00
|
|
|
exit(1);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
if (ibuf == NULL) {
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
/* OCIO_TODO: support different input color space */
|
|
|
|
|
ibuf = IMB_loadiffname(filepath, IB_rect, NULL);
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
if (ibuf == NULL) {
|
2013-07-13 12:58:00 +00:00
|
|
|
printf("%s: '%s' couldn't open\n", __func__, filepath);
|
2012-08-06 16:07:11 +00:00
|
|
|
exit(1);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
GHOST_EventConsumerHandle consumer = GHOST_CreateEventConsumer(ghost_event_proc, &ps);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
g_WS.ghost_system = GHOST_CreateSystem();
|
|
|
|
|
GHOST_AddEventConsumer(g_WS.ghost_system, consumer);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-10-28 10:09:31 -07:00
|
|
|
playanim_window_open("Blender Animation Player", start_x, start_y, ibuf->x, ibuf->y);
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &maxwinx, &maxwiny);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-01 11:09:22 +10:00
|
|
|
// GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-04-06 01:54:10 -03:00
|
|
|
/* initialize OpenGL immediate mode */
|
2020-08-06 04:30:38 +02:00
|
|
|
g_WS.gpu_context = GPU_context_create(g_WS.ghost_window);
|
2018-07-01 21:07:18 +02:00
|
|
|
GPU_init();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
/* initialize the font */
|
2017-07-08 02:07:39 +02:00
|
|
|
BLF_init();
|
2020-02-17 14:07:18 +01:00
|
|
|
ps.fontid = BLF_load_mono_default(false);
|
2012-08-06 16:07:11 +00:00
|
|
|
BLF_size(ps.fontid, 11, 72);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
ps.ibufx = ibuf->x;
|
|
|
|
|
ps.ibufy = ibuf->y;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-09 14:57:06 +00:00
|
|
|
ps.win_x = ps.ibufx;
|
|
|
|
|
ps.win_y = ps.ibufy;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-13 09:15:15 +02:00
|
|
|
if (maxwinx % ibuf->x) {
|
|
|
|
|
maxwinx = ibuf->x * (1 + (maxwinx / ibuf->x));
|
|
|
|
|
}
|
|
|
|
|
if (maxwiny % ibuf->y) {
|
|
|
|
|
maxwiny = ibuf->y * (1 + (maxwiny / ibuf->y));
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-23 11:11:27 +02:00
|
|
|
GPU_clear_color(0.1f, 0.1f, 0.1f, 0.0f);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-19 13:01:36 +01:00
|
|
|
int win_x, win_y;
|
|
|
|
|
playanim_window_get_size(&win_x, &win_y);
|
2020-07-17 19:03:30 +02:00
|
|
|
GPU_viewport(0, 0, win_x, win_y);
|
2020-07-17 19:13:43 +02:00
|
|
|
GPU_scissor(0, 0, win_x, win_y);
|
2019-02-19 13:01:36 +01:00
|
|
|
playanim_gl_matrix();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
GHOST_SwapWindowBuffers(g_WS.ghost_window);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
if (sfra == -1 || efra == -1) {
|
|
|
|
|
/* one of the frames was invalid, just use all images */
|
|
|
|
|
sfra = 1;
|
|
|
|
|
efra = MAXFRAME;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-09 14:57:06 +00:00
|
|
|
build_pict_list(&ps, filepath, (efra - sfra) + 1, ps.fstep, ps.fontid);
|
2012-08-06 16:07:11 +00:00
|
|
|
|
2015-06-12 11:47:37 +02:00
|
|
|
#ifdef WITH_AUDASPACE
|
2015-06-15 12:18:14 +02:00
|
|
|
source = AUD_Sound_file(filepath);
|
2015-06-12 11:47:37 +02:00
|
|
|
{
|
|
|
|
|
struct anim *anim_movie = ((struct PlayAnimPict *)picsbase.first)->anim;
|
|
|
|
|
if (anim_movie) {
|
|
|
|
|
short frs_sec = 25;
|
|
|
|
|
float frs_sec_base = 1.0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-06-12 11:47:37 +02:00
|
|
|
IMB_anim_get_fps(anim_movie, &frs_sec, &frs_sec_base, true);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-06-12 11:47:37 +02:00
|
|
|
fps_movie = (double)frs_sec / (double)frs_sec_base;
|
|
|
|
|
/* enforce same fps for movie as sound */
|
|
|
|
|
swaptime = ps.fstep / fps_movie;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
for (i = 2; i < argc; i++) {
|
|
|
|
|
BLI_strncpy(filepath, argv[i], sizeof(filepath));
|
2013-03-09 14:57:06 +00:00
|
|
|
build_pict_list(&ps, filepath, (efra - sfra) + 1, ps.fstep, ps.fontid);
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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) {
|
2019-04-13 09:15:15 +02:00
|
|
|
if (ps.pingpong) {
|
2012-08-06 16:07:11 +00:00
|
|
|
ps.direction = -ps.direction;
|
2019-04-13 09:15:15 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
if (ps.direction == 1) {
|
|
|
|
|
ps.picture = picsbase.first;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
ps.picture = picsbase.last;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
if (ps.picture == NULL) {
|
|
|
|
|
printf("couldn't find pictures\n");
|
2014-04-01 11:34:00 +11:00
|
|
|
ps.go = false;
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
if (ps.pingpong) {
|
|
|
|
|
if (ps.direction == 1) {
|
|
|
|
|
ps.picture = ps.picture->next;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
ps.picture = ps.picture->prev;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-13 09:15:15 +02:00
|
|
|
if (ptottime > 0.0) {
|
|
|
|
|
ptottime = 0.0;
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
|
2015-06-12 11:47:37 +02:00
|
|
|
#ifdef WITH_AUDASPACE
|
2019-04-13 09:15:15 +02:00
|
|
|
if (playback_handle) {
|
2015-06-15 12:18:14 +02:00
|
|
|
AUD_Handle_stop(playback_handle);
|
2019-04-13 09:15:15 +02:00
|
|
|
}
|
2015-06-15 12:18:14 +02:00
|
|
|
playback_handle = AUD_Device_play(audio_device, source, 1);
|
2015-06-12 11:47:37 +02:00
|
|
|
update_sound_fps();
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
while (ps.picture) {
|
2021-05-07 17:12:41 +10:00
|
|
|
bool has_event;
|
2012-08-06 16:07:11 +00:00
|
|
|
#ifndef USE_IMB_CACHE
|
2020-11-13 20:25:21 +11:00
|
|
|
if (ibuf != NULL && ibuf->ftype == IMB_FTYPE_NONE) {
|
2019-04-13 09:15:15 +02:00
|
|
|
IMB_freeImBuf(ibuf);
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
#endif
|
2021-05-07 17:49:14 +10:00
|
|
|
|
|
|
|
|
ibuf = ibuf_from_picture(ps.picture);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
if (ibuf) {
|
|
|
|
|
#ifdef USE_IMB_CACHE
|
|
|
|
|
ps.picture->ibuf = ibuf;
|
|
|
|
|
#endif
|
2015-05-16 08:34:36 +10:00
|
|
|
|
|
|
|
|
#ifdef USE_FRAME_CACHE_LIMIT
|
2021-05-06 11:22:54 +10:00
|
|
|
if (ps.picture->frame_cache_node == NULL) {
|
2021-05-07 17:53:27 +10:00
|
|
|
frame_cache_add(ps.picture);
|
2021-05-06 11:22:54 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2021-05-07 17:53:27 +10:00
|
|
|
frame_cache_touch(ps.picture);
|
2015-05-15 16:00:36 +02:00
|
|
|
}
|
2021-05-07 17:53:27 +10:00
|
|
|
frame_cache_limit_apply(ibuf);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-05-16 08:34:36 +10:00
|
|
|
#endif /* USE_FRAME_CACHE_LIMIT */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
BLI_strncpy(ibuf->name, ps.picture->name, sizeof(ibuf->name));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
/* why only windows? (from 2.4x) - campbell */
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
GHOST_SetTitle(g_WS.ghost_window, ps.picture->name);
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-04-13 09:15:15 +02:00
|
|
|
while (pupdate_time()) {
|
|
|
|
|
PIL_sleep_ms(1);
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
ptottime -= swaptime;
|
2013-03-09 14:57:06 +00:00
|
|
|
playanim_toscreen(&ps, ps.picture, ibuf, ps.fontid, ps.fstep);
|
|
|
|
|
} /* else delete */
|
2012-08-06 16:07:11 +00:00
|
|
|
else {
|
|
|
|
|
printf("error: can't play this image type\n");
|
|
|
|
|
exit(0);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
if (ps.once) {
|
|
|
|
|
if (ps.picture->next == NULL) {
|
2014-04-01 11:34:00 +11:00
|
|
|
ps.wait2 = true;
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
else if (ps.picture->prev == NULL) {
|
2014-04-01 11:34:00 +11:00
|
|
|
ps.wait2 = true;
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-12-06 06:01:15 +00:00
|
|
|
ps.next_frame = ps.direction;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-05-07 17:12:41 +10:00
|
|
|
while ((has_event = GHOST_ProcessEvents(g_WS.ghost_system, false))) {
|
2018-07-06 17:14:16 +02:00
|
|
|
GHOST_DispatchEvents(g_WS.ghost_system);
|
|
|
|
|
}
|
|
|
|
|
if (ps.go == false) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
change_frame(&ps);
|
2021-05-07 17:12:41 +10:00
|
|
|
if (!has_event) {
|
2018-07-06 17:14:16 +02:00
|
|
|
PIL_sleep_ms(1);
|
|
|
|
|
}
|
|
|
|
|
if (ps.wait2) {
|
|
|
|
|
continue;
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
ps.wait2 = ps.sstep;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-05-08 15:57:57 +10:00
|
|
|
if (ps.wait2 == false && ps.stopped) {
|
|
|
|
|
ps.stopped = false;
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
pupdate_time();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-12-06 06:01:15 +00:00
|
|
|
if (ps.picture && ps.next_frame) {
|
2021-05-08 15:50:34 +10:00
|
|
|
/* Advance to the next frame, always at least set one step.
|
|
|
|
|
* Implement frame-skipping when enabled and playback is not fast enough. */
|
2012-08-06 16:07:11 +00:00
|
|
|
while (ps.picture) {
|
2012-12-06 06:01:15 +00:00
|
|
|
ps.picture = playanim_step(ps.picture, ps.next_frame);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
if (ps.once && ps.picture != NULL) {
|
|
|
|
|
if (ps.picture->next == NULL) {
|
2014-04-01 11:34:00 +11:00
|
|
|
ps.wait2 = true;
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
else if (ps.picture->prev == NULL) {
|
2014-04-01 11:34:00 +11:00
|
|
|
ps.wait2 = true;
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2021-05-08 15:53:56 +10:00
|
|
|
if (ps.wait2 || ptottime < swaptime || ps.noskip) {
|
2019-04-13 09:15:15 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
ptottime -= swaptime;
|
|
|
|
|
}
|
|
|
|
|
if (ps.picture == NULL && ps.sstep) {
|
2012-12-06 06:01:15 +00:00
|
|
|
ps.picture = playanim_step(ps.picture, ps.next_frame);
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2014-04-01 11:34:00 +11:00
|
|
|
if (ps.go == false) {
|
2012-08-06 16:07:11 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
2015-10-15 17:45:53 +11:00
|
|
|
while ((ps.picture = BLI_pophead(&picsbase))) {
|
|
|
|
|
if (ps.picture->anim) {
|
|
|
|
|
if ((ps.picture->next == NULL) || (ps.picture->next->anim != ps.picture->anim)) {
|
|
|
|
|
IMB_close_anim(ps.picture->anim);
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
if (ps.picture->ibuf) {
|
|
|
|
|
IMB_freeImBuf(ps.picture->ibuf);
|
|
|
|
|
}
|
|
|
|
|
if (ps.picture->mem) {
|
|
|
|
|
MEM_freeN(ps.picture->mem);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-10-15 17:45:53 +11:00
|
|
|
MEM_freeN((void *)ps.picture->name);
|
|
|
|
|
MEM_freeN(ps.picture);
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
/* cleanup */
|
|
|
|
|
#ifndef USE_IMB_CACHE
|
2019-04-13 09:15:15 +02:00
|
|
|
if (ibuf) {
|
|
|
|
|
IMB_freeImBuf(ibuf);
|
|
|
|
|
}
|
2012-08-06 16:07:11 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
BLI_freelistN(&picsbase);
|
2021-05-05 17:57:16 +10:00
|
|
|
|
|
|
|
|
#ifdef USE_FRAME_CACHE_LIMIT
|
2021-05-07 17:12:41 +10:00
|
|
|
BLI_freelistN(&g_frame_cache.pics);
|
|
|
|
|
g_frame_cache.pics_len = 0;
|
2021-05-08 16:10:07 +10:00
|
|
|
g_frame_cache.pics_size_in_memory = 0;
|
2021-05-05 17:57:16 +10:00
|
|
|
#endif
|
2015-06-12 11:47:37 +02:00
|
|
|
|
|
|
|
|
#ifdef WITH_AUDASPACE
|
2015-09-03 04:12:03 +10:00
|
|
|
if (playback_handle) {
|
2015-06-15 12:18:14 +02:00
|
|
|
AUD_Handle_stop(playback_handle);
|
2015-09-03 04:12:03 +10:00
|
|
|
playback_handle = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (scrub_handle) {
|
2015-06-15 12:18:14 +02:00
|
|
|
AUD_Handle_stop(scrub_handle);
|
2015-09-03 04:12:03 +10:00
|
|
|
scrub_handle = NULL;
|
|
|
|
|
}
|
2015-06-15 12:18:14 +02:00
|
|
|
AUD_Sound_free(source);
|
2015-09-03 04:12:03 +10:00
|
|
|
source = NULL;
|
2015-06-12 11:47:37 +02:00
|
|
|
#endif
|
2012-08-06 16:07:11 +00:00
|
|
|
/* we still miss freeing a lot!,
|
|
|
|
|
* but many areas could skip initialization too for anim play */
|
2017-04-06 01:54:10 -03:00
|
|
|
|
|
|
|
|
GPU_shader_free_builtin_shaders();
|
|
|
|
|
|
2018-07-18 00:12:21 +02:00
|
|
|
if (g_WS.gpu_context) {
|
|
|
|
|
GPU_context_active_set(g_WS.gpu_context);
|
|
|
|
|
GPU_context_discard(g_WS.gpu_context);
|
|
|
|
|
g_WS.gpu_context = NULL;
|
2018-06-19 16:13:10 +02:00
|
|
|
}
|
|
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
BLF_exit();
|
2016-01-29 14:31:29 +11:00
|
|
|
|
2018-07-09 23:33:20 +02:00
|
|
|
GPU_exit();
|
|
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
GHOST_DisposeWindow(g_WS.ghost_system, g_WS.ghost_window);
|
|
|
|
|
|
2013-03-08 13:03:04 +00:00
|
|
|
/* early exit, IMB and BKE should be exited only in end */
|
2013-07-13 12:58:00 +00:00
|
|
|
if (ps.dropped_file[0]) {
|
2013-03-08 13:03:04 +00:00
|
|
|
BLI_strncpy(filepath, ps.dropped_file, sizeof(filepath));
|
|
|
|
|
return filepath;
|
|
|
|
|
}
|
2018-06-07 16:43:52 +02:00
|
|
|
|
2013-03-08 13:03:04 +00:00
|
|
|
IMB_exit();
|
|
|
|
|
BKE_images_exit();
|
2017-04-06 16:44:32 +02:00
|
|
|
DEG_free_node_types();
|
2013-03-08 13:03:04 +00:00
|
|
|
|
2012-08-06 16:07:11 +00:00
|
|
|
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
|
|
|
|
|
}
|
2018-06-07 16:43:52 +02:00
|
|
|
|
2013-03-08 13:03:04 +00:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WM_main_playanim(int argc, const char **argv)
|
|
|
|
|
{
|
2015-09-03 04:25:00 +10:00
|
|
|
const char *argv_next[2];
|
2013-03-09 03:46:30 +00:00
|
|
|
bool looping = true;
|
|
|
|
|
|
2015-09-03 04:12:03 +10:00
|
|
|
#ifdef WITH_AUDASPACE
|
|
|
|
|
{
|
|
|
|
|
AUD_DeviceSpecs specs;
|
|
|
|
|
|
2015-12-27 16:33:54 +01:00
|
|
|
specs.rate = AUD_RATE_48000;
|
2015-09-03 04:12:03 +10:00
|
|
|
specs.format = AUD_FORMAT_S16;
|
|
|
|
|
specs.channels = AUD_CHANNELS_STEREO;
|
|
|
|
|
|
|
|
|
|
AUD_initOnce();
|
|
|
|
|
|
2021-03-16 22:32:16 +01:00
|
|
|
if (!(audio_device = AUD_init(NULL, specs, 1024, "Blender"))) {
|
2021-03-16 23:45:49 +01:00
|
|
|
audio_device = AUD_init("None", specs, 0, "Blender");
|
2015-09-03 04:12:03 +10:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2013-03-08 13:03:04 +00:00
|
|
|
while (looping) {
|
2014-04-27 00:21:43 +10:00
|
|
|
const char *filepath = wm_main_playanim_intern(argc, argv);
|
2013-03-09 03:46:30 +00:00
|
|
|
|
2013-03-08 13:03:04 +00:00
|
|
|
if (filepath) { /* use simple args */
|
2015-09-03 04:25:00 +10:00
|
|
|
argv_next[0] = argv[0];
|
|
|
|
|
argv_next[1] = filepath;
|
|
|
|
|
argc = 2;
|
|
|
|
|
|
|
|
|
|
/* continue with new args */
|
|
|
|
|
argv = argv_next;
|
2013-03-08 13:03:04 +00:00
|
|
|
}
|
2013-03-09 03:46:30 +00:00
|
|
|
else {
|
|
|
|
|
looping = false;
|
|
|
|
|
}
|
2013-03-08 13:03:04 +00:00
|
|
|
}
|
2015-09-03 04:12:03 +10:00
|
|
|
|
|
|
|
|
#ifdef WITH_AUDASPACE
|
|
|
|
|
AUD_exit(audio_device);
|
|
|
|
|
AUD_exitOnce();
|
|
|
|
|
#endif
|
2012-08-06 16:07:11 +00:00
|
|
|
}
|