Compare commits
87 Commits
temp-node-
...
soc-2021-v
Author | SHA1 | Date | |
---|---|---|---|
6f908dffe2 | |||
f3d3e125b7 | |||
14d7721836 | |||
6b8a5e78de | |||
f9094bbc40 | |||
e600fc482f | |||
bec129af27 | |||
a68cdab213 | |||
9cb616d8aa | |||
5d43ea0155 | |||
95162f2aa9 | |||
427265785d | |||
0973ec24a5 | |||
1ed0d1971c | |||
8edbbf2221 | |||
95ca2cd634 | |||
ee78603b35 | |||
bf97bfb0ea | |||
a224bcbcfc | |||
b20e00bda7 | |||
3de92e5f21 | |||
e66dc4beca | |||
faf1210c0b | |||
15f33b0439 | |||
9b08f523ec | |||
f9367f9399 | |||
a31ebb5213 | |||
68e5a340b5 | |||
58677609ee | |||
4243f7fb7b | |||
e6c83f4cc0 | |||
a5b4f928fe | |||
fea8bcc25c | |||
57c79e07ce | |||
433de045b7 | |||
f96490446f | |||
72550b8dc7 | |||
8d9f03e002 | |||
8d5e49bdea | |||
00efb3d18b | |||
0ae42c6e74 | |||
dd25a095ac | |||
11b9e782df | |||
a16ac64ea7 | |||
cfcee229d2 | |||
96d8b1eb7a | |||
b0e5a377ae | |||
9e6127ac25 | |||
58c8d7377b | |||
b72584e3dd | |||
825006e202 | |||
fa003454fc | |||
3e51039ce6 | |||
a75b089b58 | |||
73a819ad20 | |||
b3862fea0b | |||
688f5a0fe0 | |||
f28759541f | |||
7d2f7886c7 | |||
114b9ef9cd | |||
caf2ee76c0 | |||
91c4e3e2a5 | |||
a28c412b46 | |||
d07dc28e0c | |||
3eb694dd3d | |||
c8c42d132a | |||
21a3dd756a | |||
bad23a721f | |||
9f5d9c1629 | |||
d2c95bd7e4 | |||
d3df935741 | |||
d802bf30b4 | |||
0374114aca | |||
2696fca1a0 | |||
ebe7abb677 | |||
c32ddae847 | |||
fbae0d75bc | |||
df579a3b6d | |||
4b03995ce5 | |||
c2b0164b6e | |||
df171bf8bc | |||
92d06984e4 | |||
dc2dc9ffaf | |||
09c28f9b16 | |||
96c50ae2ba | |||
e169120c81 | |||
b18373ef6a |
@@ -250,7 +250,8 @@ class SEQUENCER_PT_sequencer_overlay(Panel):
|
||||
layout.prop(st, "show_strip_offset", text="Offsets")
|
||||
layout.prop(st, "show_fcurves", text="F-Curves")
|
||||
layout.prop(st, "show_grid", text="Grid")
|
||||
|
||||
layout.prop(st, "show_thumbnails", text="Thumbnails")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.prop_menu_enum(st, "waveform_display_type")
|
||||
|
@@ -39,7 +39,7 @@ extern "C" {
|
||||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 20
|
||||
#define BLENDER_FILE_SUBVERSION 21
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and show a warning if the file
|
||||
|
@@ -1111,6 +1111,32 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 300, 20)) {
|
||||
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
|
||||
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
||||
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
|
||||
if (sl->spacetype == SPACE_SEQ) {
|
||||
SpaceSeq *sseq = (SpaceSeq *)sl;
|
||||
sseq->flag |= SEQ_SHOW_THUMBNAILS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 300, 21)) {
|
||||
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
|
||||
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
||||
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
|
||||
if (sl->spacetype == SPACE_SEQ) {
|
||||
SpaceSeq *sseq = (SpaceSeq *)sl;
|
||||
sseq->flag |= SEQ_SHOW_THUMBNAILS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
|
@@ -157,7 +157,7 @@ static void blo_update_defaults_screen(bScreen *screen,
|
||||
SpaceSeq *seq = area->spacedata.first;
|
||||
seq->flag |= SEQ_SHOW_MARKERS | SEQ_SHOW_FCURVES | SEQ_ZOOM_TO_FIT | SEQ_SHOW_STRIP_OVERLAY |
|
||||
SEQ_SHOW_STRIP_SOURCE | SEQ_SHOW_STRIP_NAME | SEQ_SHOW_STRIP_DURATION |
|
||||
SEQ_SHOW_GRID;
|
||||
SEQ_SHOW_GRID | SEQ_SHOW_THUMBNAILS;
|
||||
|
||||
seq->render_size = SEQ_RENDER_SIZE_PROXY_100;
|
||||
seq->flag |= SEQ_USE_PROXIES;
|
||||
|
@@ -5823,6 +5823,11 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
|
||||
icon = ICON_SEQUENCE;
|
||||
break;
|
||||
}
|
||||
if (WM_jobs_test(wm, scene, WM_JOB_TYPE_SEQ_DRAW_THUMBNAIL)) {
|
||||
handle_event = B_STOPSEQ;
|
||||
icon = ICON_SEQUENCE;
|
||||
break;
|
||||
}
|
||||
if (WM_jobs_test(wm, scene, WM_JOB_TYPE_CLIP_BUILD_PROXY)) {
|
||||
handle_event = B_STOPCLIP;
|
||||
icon = ICON_TRACKER;
|
||||
|
@@ -147,6 +147,8 @@ static void view_pan_init(bContext *C, wmOperator *op)
|
||||
const float winy = (float)(BLI_rcti_size_y(&vpd->region->winrct) + 1);
|
||||
vpd->facx = (BLI_rctf_size_x(&vpd->v2d->cur)) / winx;
|
||||
vpd->facy = (BLI_rctf_size_y(&vpd->v2d->cur)) / winy;
|
||||
|
||||
vpd->v2d->flag |= V2D_IS_NAVIGATING;
|
||||
}
|
||||
|
||||
/* apply transform to view (i.e. adjust 'cur' rect) */
|
||||
@@ -190,6 +192,8 @@ static void view_pan_apply(bContext *C, wmOperator *op)
|
||||
/* Cleanup temp custom-data. */
|
||||
static void view_pan_exit(wmOperator *op)
|
||||
{
|
||||
v2dViewPanData *vpd = op->customdata;
|
||||
vpd->v2d->flag &= ~V2D_IS_NAVIGATING;
|
||||
MEM_SAFE_FREE(op->customdata);
|
||||
}
|
||||
|
||||
@@ -305,7 +309,7 @@ static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static void view_pan_cancel(bContext *UNUSED(C), wmOperator *op)
|
||||
static void view_pan_cancel(bContext *C, wmOperator *op)
|
||||
{
|
||||
view_pan_exit(op);
|
||||
}
|
||||
@@ -358,6 +362,7 @@ static int view_edge_pan_modal(bContext *C, wmOperator *op, const wmEvent *event
|
||||
View2DEdgePanData *vpd = op->customdata;
|
||||
|
||||
if (event->val == KM_RELEASE || event->type == EVT_ESCKEY) {
|
||||
vpd->v2d->flag &= ~V2D_IS_NAVIGATING;
|
||||
MEM_SAFE_FREE(op->customdata);
|
||||
return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
|
||||
}
|
||||
@@ -371,6 +376,8 @@ static int view_edge_pan_modal(bContext *C, wmOperator *op, const wmEvent *event
|
||||
|
||||
static void view_edge_pan_cancel(bContext *UNUSED(C), wmOperator *op)
|
||||
{
|
||||
v2dViewPanData *vpd = op->customdata;
|
||||
vpd->v2d->flag &= ~V2D_IS_NAVIGATING;
|
||||
MEM_SAFE_FREE(op->customdata);
|
||||
}
|
||||
|
||||
@@ -680,6 +687,8 @@ static void view_zoomdrag_init(bContext *C, wmOperator *op)
|
||||
vzd->v2d = &vzd->region->v2d;
|
||||
/* False by default. Interactive callbacks (ie invoke()) can set it to true. */
|
||||
vzd->zoom_to_mouse_pos = false;
|
||||
|
||||
vzd->v2d->flag |= V2D_IS_NAVIGATING;
|
||||
}
|
||||
|
||||
/* apply transform to view (i.e. adjust 'cur' rect) */
|
||||
@@ -809,7 +818,8 @@ static void view_zoomstep_apply(bContext *C, wmOperator *op)
|
||||
static void view_zoomstep_exit(wmOperator *op)
|
||||
{
|
||||
UI_view2d_zoom_cache_reset();
|
||||
|
||||
v2dViewZoomData *vzd = op->customdata;
|
||||
vzd->v2d->flag &= ~V2D_IS_NAVIGATING;
|
||||
MEM_SAFE_FREE(op->customdata);
|
||||
}
|
||||
|
||||
@@ -1041,6 +1051,7 @@ static void view_zoomdrag_exit(bContext *C, wmOperator *op)
|
||||
|
||||
if (op->customdata) {
|
||||
v2dViewZoomData *vzd = op->customdata;
|
||||
vzd->v2d->flag &= ~V2D_IS_NAVIGATING;
|
||||
|
||||
if (vzd->timer) {
|
||||
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), vzd->timer);
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_threads.h"
|
||||
@@ -1277,6 +1278,391 @@ static void draw_seq_fcurve_overlay(
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct ThumbnailDrawJob {
|
||||
SeqRenderData context;
|
||||
GHash *sequences_ghash;
|
||||
Scene *scene;
|
||||
rctf *view_area;
|
||||
float pixelx;
|
||||
float pixely;
|
||||
} ThumbnailDrawJob;
|
||||
|
||||
typedef struct ThumbDataItem {
|
||||
Sequence *seq_dupli;
|
||||
Scene *scene;
|
||||
} ThumbDataItem;
|
||||
|
||||
static void thumbnail_hash_data_free(void *val)
|
||||
{
|
||||
ThumbDataItem *item = val;
|
||||
SEQ_sequence_free(item->scene, item->seq_dupli, 0);
|
||||
MEM_freeN(val);
|
||||
}
|
||||
|
||||
static void thumbnail_freejob(void *data)
|
||||
{
|
||||
ThumbnailDrawJob *tj = data;
|
||||
BLI_ghash_free(tj->sequences_ghash, NULL, thumbnail_hash_data_free);
|
||||
MEM_freeN(tj->view_area);
|
||||
MEM_freeN(tj);
|
||||
}
|
||||
|
||||
static void thumbnail_endjob(void *data)
|
||||
{
|
||||
ThumbnailDrawJob *tj = data;
|
||||
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, tj->scene);
|
||||
}
|
||||
|
||||
static bool check_seq_need_thumbnails(Sequence *seq, rctf *view_area)
|
||||
{
|
||||
if (seq->type != SEQ_TYPE_MOVIE && seq->type != SEQ_TYPE_IMAGE) {
|
||||
return false;
|
||||
}
|
||||
if (min_ii(seq->startdisp, seq->start) > view_area->xmax) {
|
||||
return false;
|
||||
}
|
||||
else if (max_ii(seq->enddisp, seq->start + seq->len) < view_area->xmin) {
|
||||
return false;
|
||||
}
|
||||
else if (seq->machine + 1.0f < view_area->ymin) {
|
||||
return false;
|
||||
}
|
||||
else if (seq->machine > view_area->ymax) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void seq_get_thumb_image_dimensions(Sequence *seq,
|
||||
float pixelx,
|
||||
float pixely,
|
||||
float *r_thumb_width,
|
||||
float *r_thumb_height,
|
||||
float *r_image_width,
|
||||
float *r_image_height)
|
||||
{
|
||||
float image_width = seq->strip->stripdata->orig_width;
|
||||
float image_height = seq->strip->stripdata->orig_height;
|
||||
|
||||
/* Fix the dimensions to be max SEQ_RENDER_THUMB_SIZE (256) for x or y. */
|
||||
float aspect_ratio = (float)image_width / image_height;
|
||||
if (image_width > image_height) {
|
||||
image_width = SEQ_RENDER_THUMB_SIZE;
|
||||
image_height = round_fl_to_int(image_width / aspect_ratio);
|
||||
}
|
||||
else {
|
||||
image_height = SEQ_RENDER_THUMB_SIZE;
|
||||
image_width = round_fl_to_int(image_height * aspect_ratio);
|
||||
}
|
||||
|
||||
/* Calculate thumb dimensions. */
|
||||
float thumb_height = (SEQ_STRIP_OFSTOP - SEQ_STRIP_OFSBOTTOM) - (20 * U.dpi_fac * pixely);
|
||||
aspect_ratio = ((float)image_width) / image_height;
|
||||
float thumb_h_px = thumb_height / pixely;
|
||||
float thumb_width = aspect_ratio * thumb_h_px * pixelx;
|
||||
|
||||
if (r_thumb_height == NULL) {
|
||||
*r_thumb_width = thumb_width;
|
||||
return;
|
||||
}
|
||||
|
||||
*r_thumb_height = thumb_height;
|
||||
*r_image_width = image_width;
|
||||
*r_image_height = image_height;
|
||||
*r_thumb_width = thumb_width;
|
||||
}
|
||||
|
||||
static float seq_thumbnail_get_start_frame(Sequence *seq, float frame_step, rctf *view_area)
|
||||
{
|
||||
if (seq->start > view_area->xmin) {
|
||||
return seq->start;
|
||||
}
|
||||
|
||||
/* Drawing and caching both check to see if stristart_framep is in view area or not before
|
||||
* calling this function so assuming strip/part of strip in view. */
|
||||
|
||||
int no_invisible_thumbs = (view_area->xmin - seq->start) / frame_step;
|
||||
return ((no_invisible_thumbs - 1) * frame_step) + seq->start;
|
||||
}
|
||||
|
||||
static void thumbnail_start_job(void *data, short *stop, short *do_update, float *progress)
|
||||
{
|
||||
ThumbnailDrawJob *tj = data;
|
||||
float start_frame, frame_step;
|
||||
|
||||
GHashIterator gh_iter;
|
||||
BLI_ghashIterator_init(&gh_iter, tj->sequences_ghash);
|
||||
while (!BLI_ghashIterator_done(&gh_iter) & !*stop) {
|
||||
Sequence *seq_orig = BLI_ghashIterator_getKey(&gh_iter);
|
||||
ThumbDataItem *val = BLI_ghash_lookup(tj->sequences_ghash, seq_orig);
|
||||
|
||||
if (check_seq_need_thumbnails(seq_orig, tj->view_area)) {
|
||||
seq_get_thumb_image_dimensions(
|
||||
val->seq_dupli, tj->pixelx, tj->pixely, &frame_step, NULL, NULL, NULL);
|
||||
start_frame = seq_thumbnail_get_start_frame(seq_orig, frame_step, tj->view_area);
|
||||
SEQ_render_thumbnails(
|
||||
&tj->context, val->seq_dupli, seq_orig, start_frame, frame_step, tj->view_area, stop);
|
||||
}
|
||||
BLI_ghashIterator_step(&gh_iter);
|
||||
}
|
||||
UNUSED_VARS(do_update, progress);
|
||||
}
|
||||
|
||||
static SeqRenderData sequencer_thumbnail_context_init(const bContext *C)
|
||||
{
|
||||
struct Main *bmain = CTX_data_main(C);
|
||||
struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
SpaceSeq *sseq = CTX_wm_space_seq(C);
|
||||
SeqRenderData context = {0};
|
||||
|
||||
/* Taking rectx and recty as 0 as dimensions not known here, and context is used to calculate
|
||||
* hash key but not necessary as other variables of SeqRenderData are unique enough. */
|
||||
SEQ_render_new_render_data(bmain, depsgraph, scene, 0, 0, sseq->render_size, false, &context);
|
||||
context.view_id = BKE_scene_multiview_view_id_get(&scene->r, STEREO_LEFT_NAME);
|
||||
context.use_proxies = false;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static GHash *sequencer_thumbnail_ghash_init(const bContext *C, View2D *v2d, Editing *ed)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
/* Set the data for thumbnail caching job. */
|
||||
GHash *thumb_data_hash = BLI_ghash_ptr_new("seq_duplicates_and_origs");
|
||||
|
||||
LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
|
||||
ThumbDataItem *val_need_update = BLI_ghash_lookup(thumb_data_hash, seq);
|
||||
if (val_need_update == NULL && check_seq_need_thumbnails(seq, &v2d->cur)) {
|
||||
ThumbDataItem *val = MEM_callocN(sizeof(ThumbDataItem), "Thumbnail Hash Values");
|
||||
val->seq_dupli = SEQ_sequence_dupli_recursive(scene, scene, NULL, seq, 0);
|
||||
val->scene = scene;
|
||||
BLI_ghash_insert(thumb_data_hash, seq, val);
|
||||
}
|
||||
else {
|
||||
if (val_need_update != NULL) {
|
||||
val_need_update->seq_dupli->start = seq->start;
|
||||
val_need_update->seq_dupli->startdisp = seq->startdisp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return thumb_data_hash;
|
||||
}
|
||||
|
||||
static void sequencer_thumbnail_init_job(const bContext *C, View2D *v2d, Editing *ed)
|
||||
{
|
||||
wmJob *wm_job;
|
||||
ThumbnailDrawJob *tj = NULL;
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
wm_job = WM_jobs_get(CTX_wm_manager(C),
|
||||
CTX_wm_window(C),
|
||||
CTX_data_scene(C),
|
||||
"Draw Thumbnails",
|
||||
0,
|
||||
WM_JOB_TYPE_SEQ_DRAW_THUMBNAIL);
|
||||
|
||||
/* Get the thumbnail job if it exists. */
|
||||
tj = WM_jobs_customdata_get(wm_job);
|
||||
if (!tj) {
|
||||
tj = MEM_callocN(sizeof(ThumbnailDrawJob), "Thumbnail cache job");
|
||||
|
||||
/* Duplicate value of v2d->cur and v2d->tot to have module separation. */
|
||||
rctf *view_area = MEM_callocN(sizeof(struct rctf), "viewport area");
|
||||
view_area->xmax = v2d->cur.xmax;
|
||||
view_area->xmin = v2d->cur.xmin;
|
||||
view_area->ymax = v2d->cur.ymax;
|
||||
view_area->ymin = v2d->cur.ymin;
|
||||
|
||||
tj->scene = CTX_data_scene(C);
|
||||
tj->view_area = view_area;
|
||||
tj->context = sequencer_thumbnail_context_init(C);
|
||||
tj->sequences_ghash = sequencer_thumbnail_ghash_init(C, v2d, ed);
|
||||
tj->pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
|
||||
tj->pixely = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
|
||||
WM_jobs_customdata_set(wm_job, tj, thumbnail_freejob);
|
||||
WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_SEQUENCER, NC_SCENE | ND_SEQUENCER);
|
||||
WM_jobs_callbacks(wm_job, thumbnail_start_job, NULL, NULL, thumbnail_endjob);
|
||||
}
|
||||
|
||||
if (!WM_jobs_is_running(wm_job)) {
|
||||
G.is_break = false;
|
||||
WM_jobs_start(CTX_wm_manager(C), wm_job);
|
||||
}
|
||||
else {
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, NULL);
|
||||
}
|
||||
|
||||
ED_area_tag_redraw(area);
|
||||
}
|
||||
|
||||
static void sequencer_thumbnail_start_job_if_necessary(const bContext *C,
|
||||
Editing *ed,
|
||||
View2D *v2d,
|
||||
bool thumbnail_is_missing)
|
||||
{
|
||||
SpaceSeq *sseq = CTX_wm_space_seq(C);
|
||||
|
||||
if ((v2d->flag & V2D_IS_NAVIGATING) != 0) {
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Leftover is set to true if missing image in strip. False when normal call to all strips done.
|
||||
*/
|
||||
if (v2d->cur.xmax != sseq->runtime.last_thumbnail_area.xmax ||
|
||||
v2d->cur.ymax != sseq->runtime.last_thumbnail_area.ymax || thumbnail_is_missing) {
|
||||
|
||||
/* Stop the job first as view has changed. Pointless to continue old job. */
|
||||
if (v2d->cur.xmax != sseq->runtime.last_thumbnail_area.xmax ||
|
||||
v2d->cur.ymax != sseq->runtime.last_thumbnail_area.ymax) {
|
||||
WM_jobs_stop(CTX_wm_manager(C), NULL, thumbnail_start_job);
|
||||
}
|
||||
|
||||
sequencer_thumbnail_init_job(C, v2d, ed);
|
||||
sseq->runtime.last_thumbnail_area = v2d->cur;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't display thumbnails only when zooming. Panning doesn't cause issues. */
|
||||
static bool sequencer_thumbnail_v2d_is_navigating(const bContext *C)
|
||||
{
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
View2D *v2d = ®ion->v2d;
|
||||
SpaceSeq *sseq = CTX_wm_space_seq(C);
|
||||
|
||||
if ((v2d->flag & V2D_IS_NAVIGATING) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double x_diff = fabs(BLI_rctf_size_x(&sseq->runtime.last_thumbnail_area) -
|
||||
BLI_rctf_size_x(&v2d->cur));
|
||||
double y_diff = fabs(BLI_rctf_size_y(&sseq->runtime.last_thumbnail_area) -
|
||||
BLI_rctf_size_y(&v2d->cur));
|
||||
return x_diff > 0.01 || y_diff > 0.01;
|
||||
}
|
||||
|
||||
static void draw_seq_strip_thumbnail(View2D *v2d,
|
||||
const bContext *C,
|
||||
Scene *scene,
|
||||
Sequence *seq,
|
||||
float y1,
|
||||
float y2,
|
||||
float pixelx,
|
||||
float pixely)
|
||||
{
|
||||
bool clipped = false;
|
||||
float image_height, image_width, thumb_width, thumb_height;
|
||||
rcti crop;
|
||||
|
||||
/* If width of the strip too small ignore drawing thumbnails. */
|
||||
if ((y2 - y1) / pixely <= 40 * U.dpi_fac)
|
||||
return;
|
||||
|
||||
if (sequencer_thumbnail_v2d_is_navigating(C)) {
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
SeqRenderData context = sequencer_thumbnail_context_init(C);
|
||||
seq_get_thumb_image_dimensions(
|
||||
seq, pixelx, pixely, &thumb_width, &thumb_height, &image_width, &image_height);
|
||||
|
||||
float thumb_y_end = y1 + thumb_height - pixely;
|
||||
float thumb_x_start = seq->start;
|
||||
|
||||
float cut_off = 0;
|
||||
float upper_thumb_bound = (seq->endstill) ? (seq->start + seq->len) : seq->enddisp;
|
||||
if (seq->type == SEQ_TYPE_IMAGE) {
|
||||
upper_thumb_bound = seq->enddisp;
|
||||
}
|
||||
|
||||
/* Start drawing. */
|
||||
|
||||
thumb_x_start = seq_thumbnail_get_start_frame(seq, thumb_width, &v2d->cur);
|
||||
float thumb_x_end;
|
||||
while (thumb_x_start < upper_thumb_bound) {
|
||||
thumb_x_end = thumb_x_start + thumb_width;
|
||||
clipped = false;
|
||||
|
||||
/* Checks to make sure that thumbs are loaded only when in view and within the confines of the
|
||||
* strip. Some may not be required but better to have conditions for safety as x1 here is
|
||||
* point to start caching from and not drawing. */
|
||||
if (thumb_x_start > v2d->cur.xmax)
|
||||
break;
|
||||
|
||||
if (thumb_x_end < v2d->cur.xmin) {
|
||||
thumb_x_start = thumb_x_end;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Ignore thumbs to the left of strip. */
|
||||
if (thumb_x_end < seq->startdisp) {
|
||||
thumb_x_start = thumb_x_end;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Set the clipping bound to show the left handle moving over thumbs and not shift thumbs. */
|
||||
if (IN_RANGE_INCL(seq->startdisp, thumb_x_start, thumb_x_end)) {
|
||||
cut_off = seq->startdisp - thumb_x_start;
|
||||
clipped = true;
|
||||
}
|
||||
|
||||
/* Clip if full thumbnail cannot be displayed. */
|
||||
if (thumb_x_end > (upper_thumb_bound)) {
|
||||
thumb_x_end = upper_thumb_bound;
|
||||
clipped = true;
|
||||
if (thumb_x_end - thumb_x_start < 1)
|
||||
break;
|
||||
}
|
||||
|
||||
float zoom_x = thumb_width / image_width;
|
||||
float zoom_y = thumb_height / image_height;
|
||||
|
||||
float cropx_min = (cut_off / pixelx) / (zoom_y / pixely);
|
||||
float cropx_max = ((thumb_x_end - thumb_x_start) / pixelx) / (zoom_y / pixely);
|
||||
if (cropx_max == (thumb_x_end - thumb_x_start)) {
|
||||
cropx_max = cropx_max + 1;
|
||||
}
|
||||
BLI_rcti_init(&crop, (int)(cropx_min), (int)cropx_max, 0, (int)(image_height)-1);
|
||||
|
||||
/* Get the image. */
|
||||
ImBuf *ibuf = SEQ_get_thumbnail(&context, seq, roundf(thumb_x_start), &crop, clipped);
|
||||
|
||||
if (!ibuf) {
|
||||
sequencer_thumbnail_start_job_if_necessary(C, scene->ed, v2d, true);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Transparency on overlap. */
|
||||
if (seq->flag & SEQ_OVERLAP) {
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
unsigned char *buf = (unsigned char *)ibuf->rect;
|
||||
for (int pixel = ibuf->x * ibuf->y; pixel--; buf += 4) {
|
||||
buf[3] = OVERLAP_ALPHA;
|
||||
}
|
||||
}
|
||||
|
||||
ED_draw_imbuf_ctx_clipping(C,
|
||||
ibuf,
|
||||
thumb_x_start + cut_off,
|
||||
y1,
|
||||
true,
|
||||
thumb_x_start + cut_off,
|
||||
y1,
|
||||
thumb_x_end,
|
||||
thumb_y_end,
|
||||
zoom_x,
|
||||
zoom_y);
|
||||
IMB_freeImBuf(ibuf);
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
cut_off = 0;
|
||||
thumb_x_start = thumb_x_end;
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw visible strips. Bounds check are already made. */
|
||||
static void draw_seq_strip(const bContext *C,
|
||||
SpaceSeq *sseq,
|
||||
@@ -1348,6 +1734,11 @@ static void draw_seq_strip(const bContext *C,
|
||||
drawmeta_contents(scene, seq, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
if ((sseq->flag & SEQ_SHOW_STRIP_OVERLAY) && (sseq->flag & SEQ_SHOW_THUMBNAILS) &&
|
||||
(seq->type == SEQ_TYPE_MOVIE || seq->type == SEQ_TYPE_IMAGE)) {
|
||||
draw_seq_strip_thumbnail(v2d, C, scene, seq, y1, y2, pixelx, pixely);
|
||||
}
|
||||
|
||||
if ((sseq->flag & SEQ_SHOW_STRIP_OVERLAY) && (sseq->flag & SEQ_SHOW_FCURVES)) {
|
||||
draw_seq_fcurve_overlay(scene, v2d, seq, x1, y1, x2, y2, pixelx);
|
||||
}
|
||||
@@ -2194,6 +2585,8 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *region)
|
||||
int sel = 0, j;
|
||||
float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
|
||||
|
||||
sequencer_thumbnail_start_job_if_necessary(C, ed, v2d, false);
|
||||
|
||||
/* Loop through twice, first unselected, then selected. */
|
||||
for (j = 0; j < 2; j++) {
|
||||
Sequence *seq;
|
||||
|
@@ -579,7 +579,6 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
|
||||
static bool sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
|
||||
{
|
||||
/* Only data types supported for now. */
|
||||
Editing *ed = SEQ_editing_get(scene);
|
||||
bool changed = false;
|
||||
|
||||
/* Iterate in reverse so meta-strips are iterated after their children. */
|
||||
@@ -633,7 +632,10 @@ static bool sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
SEQ_relations_free_imbuf(scene, &ed->seqbase, false);
|
||||
for (int i = data->num_seq - 1; i >= 0; i--) {
|
||||
Sequence *seq = data->seq_array[i];
|
||||
SEQ_relations_invalidate_cache_preprocessed(scene, seq);
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
@@ -100,8 +100,11 @@ static SpaceLink *sequencer_create(const ScrArea *UNUSED(area), const Scene *sce
|
||||
sseq->mainb = SEQ_DRAW_IMG_IMBUF;
|
||||
sseq->flag = SEQ_SHOW_GPENCIL | SEQ_USE_ALPHA | SEQ_SHOW_MARKERS | SEQ_SHOW_FCURVES |
|
||||
SEQ_ZOOM_TO_FIT | SEQ_SHOW_STRIP_OVERLAY | SEQ_SHOW_STRIP_NAME |
|
||||
SEQ_SHOW_STRIP_SOURCE | SEQ_SHOW_STRIP_DURATION | SEQ_SHOW_GRID;
|
||||
SEQ_SHOW_STRIP_SOURCE | SEQ_SHOW_STRIP_DURATION | SEQ_SHOW_GRID |
|
||||
SEQ_SHOW_THUMBNAILS;
|
||||
|
||||
struct rctf temp = {0, 0, 0, 0};
|
||||
sseq->runtime.last_thumbnail_area = temp;
|
||||
/* Tool header. */
|
||||
region = MEM_callocN(sizeof(ARegion), "tool header for sequencer");
|
||||
|
||||
|
@@ -722,6 +722,7 @@ enum {
|
||||
|
||||
SEQ_CACHE_PREFETCH_ENABLE = (1 << 10),
|
||||
SEQ_CACHE_DISK_CACHE_ENABLE = (1 << 11),
|
||||
SEQ_CACHE_STORE_THUMBNAIL = (1 << 12),
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@@ -576,6 +576,10 @@ typedef enum eSpaceNla_Flag {
|
||||
/** \name Sequence Editor
|
||||
* \{ */
|
||||
|
||||
typedef struct SpaceSeqRuntime {
|
||||
struct rctf last_thumbnail_area;
|
||||
} SpaceSeqRuntime;
|
||||
|
||||
/* Sequencer */
|
||||
typedef struct SpaceSeq {
|
||||
SpaceLink *next, *prev;
|
||||
@@ -616,6 +620,10 @@ typedef struct SpaceSeq {
|
||||
/** Multiview current eye - for internal use. */
|
||||
char multiview_eye;
|
||||
char _pad2[7];
|
||||
|
||||
/** Required for Thumbnail caching job call condition */
|
||||
SpaceSeqRuntime runtime;
|
||||
|
||||
} SpaceSeq;
|
||||
|
||||
/* SpaceSeq.mainb */
|
||||
@@ -655,6 +663,7 @@ typedef enum eSpaceSeq_Flag {
|
||||
SEQ_SHOW_STRIP_DURATION = (1 << 16),
|
||||
SEQ_USE_PROXIES = (1 << 17),
|
||||
SEQ_SHOW_GRID = (1 << 18),
|
||||
SEQ_SHOW_THUMBNAILS = (1 << 19),
|
||||
} eSpaceSeq_Flag;
|
||||
|
||||
/* SpaceSeq.view */
|
||||
|
@@ -132,6 +132,8 @@ enum {
|
||||
V2D_PIXELOFS_X = (1 << 2),
|
||||
/* apply pixel offsets on y-axis when setting view matrices */
|
||||
V2D_PIXELOFS_Y = (1 << 3),
|
||||
/* zoom, pan or similar action is in progress */
|
||||
V2D_IS_NAVIGATING = (1 << 9),
|
||||
/* view settings need to be set still... */
|
||||
V2D_IS_INIT = (1 << 10),
|
||||
};
|
||||
|
@@ -5561,6 +5561,11 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_GRID);
|
||||
RNA_def_property_ui_text(prop, "Show Grid", "Show vertical grid lines");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "show_thumbnails", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_THUMBNAILS);
|
||||
RNA_def_property_ui_text(prop, "Show Thumbnails", "Show strip thumbnails");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
|
||||
}
|
||||
|
||||
static void rna_def_space_text(BlenderRNA *brna)
|
||||
|
@@ -27,6 +27,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SEQ_RENDER_THUMB_SIZE 256
|
||||
|
||||
struct ListBase;
|
||||
struct Main;
|
||||
struct Scene;
|
||||
@@ -67,6 +69,15 @@ struct ImBuf *SEQ_render_give_ibuf(const SeqRenderData *context,
|
||||
struct ImBuf *SEQ_render_give_ibuf_direct(const SeqRenderData *context,
|
||||
float timeline_frame,
|
||||
struct Sequence *seq);
|
||||
void SEQ_render_thumbnails(struct SeqRenderData *context,
|
||||
struct Sequence *seq,
|
||||
struct Sequence *seq_orig,
|
||||
float start_frame,
|
||||
float frame_step,
|
||||
rctf *view_area,
|
||||
short *stop);
|
||||
struct ImBuf *SEQ_get_thumbnail(
|
||||
SeqRenderData *context, struct Sequence *seq, float timeline_frame, rcti *crop, bool clipped);
|
||||
void SEQ_render_init_colorspace(struct Sequence *seq);
|
||||
void SEQ_render_new_render_data(struct Main *bmain,
|
||||
struct Depsgraph *depsgraph,
|
||||
|
@@ -104,6 +104,7 @@
|
||||
#define DCACHE_IMAGES_PER_FILE 100
|
||||
#define DCACHE_CURRENT_VERSION 2
|
||||
#define COLORSPACE_NAME_MAX 64 /* XXX: defined in imb intern */
|
||||
#define THUMB_CACHE_LIMIT 5000
|
||||
|
||||
typedef struct DiskCacheHeaderEntry {
|
||||
unsigned char encoding;
|
||||
@@ -148,6 +149,7 @@ typedef struct SeqCache {
|
||||
struct BLI_mempool *items_pool;
|
||||
struct SeqCacheKey *last_key;
|
||||
SeqDiskCache *disk_cache;
|
||||
int thumbnail_count;
|
||||
} SeqCache;
|
||||
|
||||
typedef struct SeqCacheItem {
|
||||
@@ -776,7 +778,7 @@ static float seq_cache_timeline_frame_to_frame_index(Sequence *seq, float timeli
|
||||
/* With raw images, map timeline_frame to strip input media frame range. This means that static
|
||||
* images or extended frame range of movies will only generate one cache entry. No special
|
||||
* treatment in converting frame index to timeline_frame is needed. */
|
||||
if (type == SEQ_CACHE_STORE_RAW) {
|
||||
if (type == SEQ_CACHE_STORE_RAW || type == SEQ_CACHE_STORE_THUMBNAIL) {
|
||||
return seq_give_frame_index(seq, timeline_frame);
|
||||
}
|
||||
|
||||
@@ -875,7 +877,7 @@ static void seq_cache_put_ex(Scene *scene, SeqCacheKey *key, ImBuf *ibuf)
|
||||
if (BLI_ghash_reinsert(cache->hash, key, item, seq_cache_keyfree, seq_cache_valfree)) {
|
||||
IMB_refImBuf(ibuf);
|
||||
|
||||
if (!key->is_temp_cache) {
|
||||
if (!key->is_temp_cache || key->type != SEQ_CACHE_STORE_THUMBNAIL) {
|
||||
cache->last_key = key;
|
||||
}
|
||||
}
|
||||
@@ -1161,6 +1163,7 @@ static void seq_cache_create(Main *bmain, Scene *scene)
|
||||
cache->hash = BLI_ghash_new(seq_cache_hashhash, seq_cache_hashcmp, "SeqCache hash");
|
||||
cache->last_key = NULL;
|
||||
cache->bmain = bmain;
|
||||
cache->thumbnail_count = 0;
|
||||
BLI_mutex_init(&cache->iterator_mutex);
|
||||
scene->ed->cache = cache;
|
||||
|
||||
@@ -1217,7 +1220,7 @@ void seq_cache_free_temp_cache(Scene *scene, short id, int timeline_frame)
|
||||
SeqCacheKey *key = BLI_ghashIterator_getKey(&gh_iter);
|
||||
BLI_ghashIterator_step(&gh_iter);
|
||||
|
||||
if (key->is_temp_cache && key->task_id == id) {
|
||||
if (key->is_temp_cache && key->task_id == id && key->type != SEQ_CACHE_STORE_THUMBNAIL) {
|
||||
/* Use frame_index here to avoid freeing raw images if they are used for multiple frames. */
|
||||
float frame_index = seq_cache_timeline_frame_to_frame_index(
|
||||
key->seq, timeline_frame, key->type);
|
||||
@@ -1278,6 +1281,7 @@ void SEQ_cache_cleanup(Scene *scene)
|
||||
BLI_ghash_remove(cache->hash, key, seq_cache_keyfree, seq_cache_valfree);
|
||||
}
|
||||
cache->last_key = NULL;
|
||||
cache->thumbnail_count = 0;
|
||||
seq_cache_unlock(scene);
|
||||
}
|
||||
|
||||
@@ -1345,6 +1349,39 @@ void seq_cache_cleanup_sequence(Scene *scene,
|
||||
seq_cache_unlock(scene);
|
||||
}
|
||||
|
||||
void seq_cache_thumbnail_cleanup(Scene *scene, rctf *view_area_safe)
|
||||
{
|
||||
/* Add offsets to the left and right end to keep some frames in cache. */
|
||||
view_area_safe->xmax += 200;
|
||||
view_area_safe->xmin -= 200;
|
||||
view_area_safe->ymin -= 1;
|
||||
view_area_safe->ymax += 1;
|
||||
|
||||
SeqCache *cache = seq_cache_get_from_scene(scene);
|
||||
if (!cache) {
|
||||
return;
|
||||
}
|
||||
|
||||
GHashIterator gh_iter;
|
||||
BLI_ghashIterator_init(&gh_iter, cache->hash);
|
||||
while (!BLI_ghashIterator_done(&gh_iter)) {
|
||||
SeqCacheKey *key = BLI_ghashIterator_getKey(&gh_iter);
|
||||
BLI_ghashIterator_step(&gh_iter);
|
||||
|
||||
if ((key->type & SEQ_CACHE_STORE_THUMBNAIL) &&
|
||||
(key->timeline_frame > view_area_safe->xmax ||
|
||||
key->timeline_frame < view_area_safe->xmin || key->seq->machine > view_area_safe->ymax ||
|
||||
key->seq->machine < view_area_safe->ymin)) {
|
||||
if (key->link_next || key->link_prev) {
|
||||
seq_cache_relink_keys(key->link_next, key->link_prev);
|
||||
}
|
||||
cache->thumbnail_count--;
|
||||
BLI_ghash_remove(cache->hash, key, seq_cache_keyfree, seq_cache_valfree);
|
||||
}
|
||||
}
|
||||
cache->last_key = NULL;
|
||||
}
|
||||
|
||||
struct ImBuf *seq_cache_get(const SeqRenderData *context,
|
||||
Sequence *seq,
|
||||
float timeline_frame,
|
||||
@@ -1436,6 +1473,37 @@ bool seq_cache_put_if_possible(
|
||||
return false;
|
||||
}
|
||||
|
||||
void seq_cache_thumbnail_put(
|
||||
const SeqRenderData *context, Sequence *seq, float timeline_frame, ImBuf *i, rctf *view_area)
|
||||
{
|
||||
Scene *scene = context->scene;
|
||||
|
||||
if (!scene->ed->cache) {
|
||||
seq_cache_create(context->bmain, scene);
|
||||
}
|
||||
|
||||
seq_cache_lock(scene);
|
||||
SeqCache *cache = seq_cache_get_from_scene(scene);
|
||||
SeqCacheKey *key = seq_cache_allocate_key(
|
||||
cache, context, seq, timeline_frame, SEQ_CACHE_STORE_THUMBNAIL);
|
||||
|
||||
/* Prevent reinserting, it breaks cache key linking. */
|
||||
if (BLI_ghash_haskey(cache->hash, key)) {
|
||||
seq_cache_unlock(scene);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Limit cache to THUMB_CACHE_LIMIT (5000) images stored. */
|
||||
if (cache->thumbnail_count >= THUMB_CACHE_LIMIT) {
|
||||
rctf view_area_safe = *view_area;
|
||||
seq_cache_thumbnail_cleanup(scene, &view_area_safe);
|
||||
}
|
||||
|
||||
seq_cache_put_ex(scene, key, i);
|
||||
cache->thumbnail_count++;
|
||||
seq_cache_unlock(scene);
|
||||
}
|
||||
|
||||
void seq_cache_put(
|
||||
const SeqRenderData *context, Sequence *seq, float timeline_frame, int type, ImBuf *i)
|
||||
{
|
||||
|
@@ -46,6 +46,11 @@ void seq_cache_put(const struct SeqRenderData *context,
|
||||
float timeline_frame,
|
||||
int type,
|
||||
struct ImBuf *i);
|
||||
void seq_cache_thumbnail_put(const struct SeqRenderData *context,
|
||||
struct Sequence *seq,
|
||||
float timeline_frame,
|
||||
struct ImBuf *i,
|
||||
rctf *view_area);
|
||||
bool seq_cache_put_if_possible(const struct SeqRenderData *context,
|
||||
struct Sequence *seq,
|
||||
float timeline_frame,
|
||||
@@ -60,6 +65,7 @@ void seq_cache_cleanup_sequence(struct Scene *scene,
|
||||
struct Sequence *seq_changed,
|
||||
int invalidate_types,
|
||||
bool force_seq_changed_range);
|
||||
void seq_cache_thumbnail_cleanup(Scene *scene, rctf *view_area);
|
||||
bool seq_cache_is_full(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@@ -527,6 +527,31 @@ static void sequencer_image_crop_init(const Sequence *seq,
|
||||
BLI_rctf_init(r_crop, left, in->x - right, bottom, in->y - top);
|
||||
}
|
||||
|
||||
static void sequencer_thumbnail_transform(ImBuf *in, ImBuf *out)
|
||||
{
|
||||
float image_scale_factor = (float)out->x / in->x;
|
||||
float transform_matrix[3][3];
|
||||
|
||||
/* Set to keep same loc,scale,rot but change scale to thumb size limit. */
|
||||
const float scale_x = 1 * image_scale_factor;
|
||||
const float scale_y = 1 * image_scale_factor;
|
||||
const float image_center_offs_x = (out->x - in->x) / 2;
|
||||
const float image_center_offs_y = (out->y - in->y) / 2;
|
||||
const float pivot[2] = {in->x / 2, in->y / 2};
|
||||
loc_rot_size_to_mat3(transform_matrix,
|
||||
(const float[]){image_center_offs_x, image_center_offs_y},
|
||||
0,
|
||||
(const float[]){scale_x, scale_y});
|
||||
transform_pivot_set_m3(transform_matrix, pivot);
|
||||
invert_m3(transform_matrix);
|
||||
|
||||
/* No crop. */
|
||||
rctf source_crop;
|
||||
BLI_rctf_init(&source_crop, 0, in->x, 0, in->y);
|
||||
|
||||
IMB_transform(in, out, transform_matrix, &source_crop, IMB_FILTER_NEAREST);
|
||||
}
|
||||
|
||||
static void sequencer_preprocess_transform_crop(
|
||||
ImBuf *in, ImBuf *out, const SeqRenderData *context, Sequence *seq, const bool is_proxy_image)
|
||||
{
|
||||
@@ -1989,7 +2014,103 @@ ImBuf *SEQ_render_give_ibuf_direct(const SeqRenderData *context,
|
||||
seq_render_state_init(&state);
|
||||
|
||||
ImBuf *ibuf = seq_render_strip(context, &state, seq, timeline_frame);
|
||||
|
||||
return ibuf;
|
||||
}
|
||||
|
||||
/* Gets the direct image from source and scales to thumbnail size. */
|
||||
static ImBuf *seq_get_uncached_thumbnail(SeqRenderData *context,
|
||||
SeqRenderState *state,
|
||||
Sequence *seq,
|
||||
float timeline_frame)
|
||||
{
|
||||
bool is_proxy_image = false;
|
||||
ImBuf *ibuf = do_render_strip_uncached(context, state, seq, timeline_frame, &is_proxy_image);
|
||||
|
||||
if (ibuf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
float aspect_ratio = (float)ibuf->x / ibuf->y;
|
||||
int rectx, recty;
|
||||
/* Calculate new dimensions - THUMB_SIZE (256) for x or y. */
|
||||
if (ibuf->x > ibuf->y) {
|
||||
rectx = SEQ_RENDER_THUMB_SIZE;
|
||||
recty = round_fl_to_int(rectx / aspect_ratio);
|
||||
}
|
||||
else {
|
||||
recty = SEQ_RENDER_THUMB_SIZE;
|
||||
rectx = round_fl_to_int(recty * aspect_ratio);
|
||||
}
|
||||
|
||||
/* Scale ibuf to thumbnail size. */
|
||||
ImBuf *scaled_ibuf = IMB_allocImBuf(rectx, recty, 32, ibuf->rect_float ? IB_rectfloat : IB_rect);
|
||||
sequencer_thumbnail_transform(ibuf, scaled_ibuf);
|
||||
seq_imbuf_assign_spaces(context->scene, scaled_ibuf);
|
||||
IMB_freeImBuf(ibuf);
|
||||
|
||||
return scaled_ibuf;
|
||||
}
|
||||
|
||||
/* Get cached thumbnails. */
|
||||
ImBuf *SEQ_get_thumbnail(
|
||||
SeqRenderData *context, Sequence *seq, float timeline_frame, rcti *crop, bool clipped)
|
||||
{
|
||||
ImBuf *ibuf = seq_cache_get(context, seq, roundf(timeline_frame), SEQ_CACHE_STORE_THUMBNAIL);
|
||||
|
||||
if (!clipped || ibuf == NULL) {
|
||||
return ibuf;
|
||||
}
|
||||
|
||||
/* Do clipping. */
|
||||
ImBuf *ibuf_cropped = IMB_dupImBuf(ibuf);
|
||||
if (crop->xmin < 0 || crop->ymin < 0) {
|
||||
crop->xmin = 0;
|
||||
crop->ymin = 0;
|
||||
}
|
||||
if (crop->xmax >= ibuf->x || crop->ymax >= ibuf->y) {
|
||||
crop->xmax = ibuf->x - 1;
|
||||
crop->ymax = ibuf->y - 1;
|
||||
}
|
||||
IMB_rect_crop(ibuf_cropped, crop);
|
||||
IMB_freeImBuf(ibuf);
|
||||
return ibuf_cropped;
|
||||
}
|
||||
|
||||
/* Render the series of thumbnails and store in cache. */
|
||||
void SEQ_render_thumbnails(SeqRenderData *context,
|
||||
Sequence *seq,
|
||||
Sequence *seq_orig,
|
||||
float start_frame,
|
||||
float frame_step,
|
||||
rctf *view_area,
|
||||
short *stop)
|
||||
{
|
||||
SeqRenderState state;
|
||||
seq_render_state_init(&state);
|
||||
|
||||
/* Adding the hold offset value (seq->anim_startofs) to the start frame. Position of image not
|
||||
* affected, but frame loaded affected. */
|
||||
start_frame = start_frame - 5 * frame_step;
|
||||
float upper_thumb_bound = (seq->endstill) ? (seq->start + seq->len) : seq->enddisp;
|
||||
upper_thumb_bound = (upper_thumb_bound > view_area->xmax) ? view_area->xmax + 5 * frame_step :
|
||||
upper_thumb_bound;
|
||||
|
||||
while ((start_frame < upper_thumb_bound) & !*stop) {
|
||||
ImBuf *ibuf = seq_cache_get(context, seq_orig, roundf(start_frame), SEQ_CACHE_STORE_THUMBNAIL);
|
||||
if (ibuf) {
|
||||
IMB_freeImBuf(ibuf);
|
||||
start_frame += frame_step;
|
||||
continue;
|
||||
}
|
||||
|
||||
ibuf = seq_get_uncached_thumbnail(context, &state, seq, roundf(start_frame));
|
||||
|
||||
if (ibuf) {
|
||||
seq_cache_thumbnail_put(context, seq_orig, roundf(start_frame), ibuf, view_area);
|
||||
IMB_freeImBuf(ibuf);
|
||||
}
|
||||
|
||||
start_frame += frame_step;
|
||||
}
|
||||
}
|
||||
/** \} */
|
||||
|
@@ -781,6 +781,7 @@ enum {
|
||||
WM_JOB_TYPE_QUADRIFLOW_REMESH,
|
||||
WM_JOB_TYPE_TRACE_IMAGE,
|
||||
WM_JOB_TYPE_LINEART,
|
||||
WM_JOB_TYPE_SEQ_DRAW_THUMBNAIL,
|
||||
/* add as needed, bake, seq proxy build
|
||||
* if having hard coded values is a problem */
|
||||
};
|
||||
|
@@ -230,7 +230,7 @@ bool WM_jobs_test(const wmWindowManager *wm, const void *owner, int job_type)
|
||||
LISTBASE_FOREACH (wmJob *, wm_job, &wm->jobs) {
|
||||
if (wm_job->owner == owner) {
|
||||
if (ELEM(job_type, WM_JOB_TYPE_ANY, wm_job->job_type)) {
|
||||
if (wm_job->running || wm_job->suspended) {
|
||||
if ((wm_job->flag & WM_JOB_PROGRESS) && (wm_job->running || wm_job->suspended)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user