VSE: Update first thumbnail when moving handle
When handles are moved, job is created only for strips that need to update first thumbnail. ref T91618
This commit is contained in:
parent
17eb8a9ceb
commit
29b9187b32
Notes:
blender-bot
2023-02-13 22:37:44 +01:00
Referenced by issue #91618, VSE thumbnails improvements
|
@ -86,6 +86,11 @@ static bool check_seq_need_thumbnails(Sequence *seq, rctf *view_area)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Handle is moved, but not for this strip. */
|
||||
if ((G.moving & G_TRANSFORM_SEQ) != 0 && (seq->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -123,26 +128,13 @@ static void seq_get_thumb_image_dimensions(Sequence *seq,
|
|||
}
|
||||
}
|
||||
|
||||
static float seq_thumbnail_get_start_frame(Sequence *seq, float frame_step, rctf *view_area)
|
||||
{
|
||||
if (seq->start > view_area->xmin && seq->start < view_area->xmax) {
|
||||
return seq->start;
|
||||
}
|
||||
|
||||
/* Drawing and caching both check to see if strip 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 *UNUSED(do_update),
|
||||
float *UNUSED(progress))
|
||||
{
|
||||
ThumbnailDrawJob *tj = data;
|
||||
float start_frame, frame_step;
|
||||
float frame_step;
|
||||
|
||||
GHashIterator gh_iter;
|
||||
|
||||
|
@ -155,9 +147,8 @@ static void thumbnail_start_job(void *data,
|
|||
if (check_seq_need_thumbnails(seq_orig, tj->view_area)) {
|
||||
seq_get_thumb_image_dimensions(
|
||||
val->seq_dupli, tj->pixelx, tj->pixely, &frame_step, tj->thumb_height, 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);
|
||||
&tj->context, val->seq_dupli, seq_orig, frame_step, tj->view_area, stop);
|
||||
SEQ_relations_sequence_free_anim(val->seq_dupli);
|
||||
}
|
||||
BLI_ghashIterator_step(&gh_iter);
|
||||
|
@ -172,7 +163,6 @@ static void thumbnail_start_job(void *data,
|
|||
if (check_seq_need_thumbnails(seq_orig, tj->view_area)) {
|
||||
seq_get_thumb_image_dimensions(
|
||||
val->seq_dupli, tj->pixelx, tj->pixely, &frame_step, tj->thumb_height, NULL, NULL);
|
||||
start_frame = seq_thumbnail_get_start_frame(seq_orig, frame_step, tj->view_area);
|
||||
SEQ_render_thumbnails_base_set(&tj->context, val->seq_dupli, seq_orig, tj->view_area, stop);
|
||||
SEQ_relations_sequence_free_anim(val->seq_dupli);
|
||||
}
|
||||
|
@ -458,40 +448,31 @@ void draw_seq_strip_thumbnail(View2D *v2d,
|
|||
upper_thumb_bound = seq->enddisp;
|
||||
}
|
||||
|
||||
float thumb_x_start = seq_thumbnail_get_start_frame(seq, thumb_width, &v2d->cur);
|
||||
float timeline_frame = SEQ_render_thumbnail_first_frame_get(seq, thumb_width, &v2d->cur);
|
||||
float thumb_x_end;
|
||||
|
||||
while (thumb_x_start + thumb_width < v2d->cur.xmin) {
|
||||
thumb_x_start += thumb_width;
|
||||
}
|
||||
|
||||
/* Ignore thumbs to the left of strip. */
|
||||
while (thumb_x_start + thumb_width < seq->startdisp) {
|
||||
thumb_x_start += thumb_width;
|
||||
}
|
||||
|
||||
GSet *last_displayed_thumbnails = last_displayed_thumbnails_list_ensure(C, seq);
|
||||
/* Cleanup thumbnail list outside of rendered range, which is cleaned up one by one to prevent
|
||||
* flickering after zooming. */
|
||||
if (!sequencer_thumbnail_v2d_is_navigating(C)) {
|
||||
last_displayed_thumbnails_list_cleanup(last_displayed_thumbnails, -FLT_MAX, thumb_x_start);
|
||||
last_displayed_thumbnails_list_cleanup(last_displayed_thumbnails, -FLT_MAX, timeline_frame);
|
||||
}
|
||||
|
||||
/* Start drawing. */
|
||||
while (thumb_x_start < upper_thumb_bound) {
|
||||
thumb_x_end = thumb_x_start + thumb_width;
|
||||
while (timeline_frame < upper_thumb_bound) {
|
||||
thumb_x_end = timeline_frame + 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) {
|
||||
if (timeline_frame > v2d->cur.xmax) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
if (IN_RANGE_INCL(seq->startdisp, timeline_frame, thumb_x_end)) {
|
||||
cut_off = seq->startdisp - timeline_frame;
|
||||
clipped = true;
|
||||
}
|
||||
|
||||
|
@ -499,7 +480,7 @@ void draw_seq_strip_thumbnail(View2D *v2d,
|
|||
if (thumb_x_end > (upper_thumb_bound)) {
|
||||
thumb_x_end = upper_thumb_bound;
|
||||
clipped = true;
|
||||
if (thumb_x_end - thumb_x_start < 1) {
|
||||
if (thumb_x_end - timeline_frame < 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -508,14 +489,12 @@ void draw_seq_strip_thumbnail(View2D *v2d,
|
|||
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)) {
|
||||
float cropx_max = ((thumb_x_end - timeline_frame) / pixelx) / (zoom_y / pixely);
|
||||
if (cropx_max == (thumb_x_end - timeline_frame)) {
|
||||
cropx_max = cropx_max + 1;
|
||||
}
|
||||
BLI_rcti_init(&crop, (int)(cropx_min), (int)cropx_max, 0, (int)(image_height)-1);
|
||||
|
||||
int timeline_frame = round_fl_to_int(thumb_x_start);
|
||||
|
||||
/* Get the image. */
|
||||
ImBuf *ibuf = SEQ_get_thumbnail(&context, seq, timeline_frame, &crop, clipped);
|
||||
|
||||
|
@ -529,7 +508,7 @@ void draw_seq_strip_thumbnail(View2D *v2d,
|
|||
else if (!sequencer_thumbnail_v2d_is_navigating(C)) {
|
||||
/* Clear images in frame range occupied by new thumbnail. */
|
||||
last_displayed_thumbnails_list_cleanup(
|
||||
last_displayed_thumbnails, thumb_x_start, thumb_x_end);
|
||||
last_displayed_thumbnails, timeline_frame, thumb_x_end);
|
||||
/* Insert new thumbnail frame to list. */
|
||||
BLI_gset_add(last_displayed_thumbnails, POINTER_FROM_INT(timeline_frame));
|
||||
}
|
||||
|
@ -558,10 +537,10 @@ void draw_seq_strip_thumbnail(View2D *v2d,
|
|||
|
||||
ED_draw_imbuf_ctx_clipping(C,
|
||||
ibuf,
|
||||
thumb_x_start + cut_off,
|
||||
timeline_frame + cut_off,
|
||||
y1,
|
||||
true,
|
||||
thumb_x_start + cut_off,
|
||||
timeline_frame + cut_off,
|
||||
y1,
|
||||
thumb_x_end,
|
||||
thumb_y_end,
|
||||
|
@ -570,7 +549,7 @@ void draw_seq_strip_thumbnail(View2D *v2d,
|
|||
IMB_freeImBuf(ibuf);
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
cut_off = 0;
|
||||
thumb_x_start += thumb_width;
|
||||
timeline_frame = SEQ_render_thumbnail_next_frame_get(seq, timeline_frame, thumb_width);
|
||||
}
|
||||
last_displayed_thumbnails_list_cleanup(last_displayed_thumbnails, thumb_x_start, FLT_MAX);
|
||||
last_displayed_thumbnails_list_cleanup(last_displayed_thumbnails, timeline_frame, FLT_MAX);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ struct ListBase;
|
|||
struct Main;
|
||||
struct Scene;
|
||||
struct Sequence;
|
||||
struct rctf;
|
||||
|
||||
typedef enum eSeqTaskId {
|
||||
SEQ_TASK_MAIN_RENDER,
|
||||
|
@ -64,7 +65,6 @@ struct ImBuf *SEQ_render_give_ibuf_direct(const SeqRenderData *context,
|
|||
void SEQ_render_thumbnails(const struct SeqRenderData *context,
|
||||
struct Sequence *seq,
|
||||
struct Sequence *seq_orig,
|
||||
float start_frame,
|
||||
float frame_step,
|
||||
rctf *view_area,
|
||||
const short *stop);
|
||||
|
@ -76,6 +76,18 @@ struct ImBuf *SEQ_get_thumbnail(const struct SeqRenderData *context,
|
|||
float timeline_frame,
|
||||
rcti *crop,
|
||||
bool clipped);
|
||||
/**
|
||||
* Get frame for first thumbnail.
|
||||
*/
|
||||
float SEQ_render_thumbnail_first_frame_get(struct Sequence *seq,
|
||||
float frame_step,
|
||||
struct rctf *view_area);
|
||||
/**
|
||||
* Get frame for first thumbnail.
|
||||
*/
|
||||
float SEQ_render_thumbnail_next_frame_get(struct Sequence *seq,
|
||||
float last_frame,
|
||||
float frame_step);
|
||||
/**
|
||||
* Get frame step for equally spaced thumbnails. These thumbnails should always be present in
|
||||
* memory, so they can be used when zooming.
|
||||
|
|
|
@ -1992,6 +1992,32 @@ ImBuf *SEQ_render_give_ibuf_direct(const SeqRenderData *context,
|
|||
return ibuf;
|
||||
}
|
||||
|
||||
float SEQ_render_thumbnail_first_frame_get(Sequence *seq, float frame_step, rctf *view_area)
|
||||
{
|
||||
int first_drawable_frame = max_iii(seq->startdisp, seq->start, view_area->xmin);
|
||||
|
||||
/* First frame should correspond to handle position. */
|
||||
if (first_drawable_frame == seq->startdisp) {
|
||||
return seq->startdisp;
|
||||
}
|
||||
|
||||
float aligned_frame_offset = (int)((first_drawable_frame - seq->start) / frame_step) *
|
||||
frame_step;
|
||||
return seq->start + aligned_frame_offset;
|
||||
}
|
||||
|
||||
float SEQ_render_thumbnail_next_frame_get(Sequence *seq, float last_frame, float frame_step)
|
||||
{
|
||||
float next_frame = last_frame + frame_step;
|
||||
|
||||
/* If handle position was displayed, align next frame with `seq->start`. */
|
||||
if (last_frame == seq->startdisp) {
|
||||
next_frame = seq->start + ((int)((last_frame - seq->start) / frame_step) + 1) * frame_step;
|
||||
}
|
||||
|
||||
return next_frame;
|
||||
}
|
||||
|
||||
/* Gets the direct image from source and scales to thumbnail size. */
|
||||
static ImBuf *seq_get_uncached_thumbnail(const SeqRenderData *context,
|
||||
SeqRenderState *state,
|
||||
|
@ -2053,7 +2079,6 @@ ImBuf *SEQ_get_thumbnail(
|
|||
void SEQ_render_thumbnails(const SeqRenderData *context,
|
||||
Sequence *seq,
|
||||
Sequence *seq_orig,
|
||||
float start_frame,
|
||||
float frame_step,
|
||||
rctf *view_area,
|
||||
const short *stop)
|
||||
|
@ -2063,24 +2088,24 @@ void SEQ_render_thumbnails(const SeqRenderData *context,
|
|||
|
||||
/* 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 - 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 + frame_step :
|
||||
upper_thumb_bound;
|
||||
|
||||
while ((start_frame < upper_thumb_bound) & !*stop) {
|
||||
float timeline_frame = SEQ_render_thumbnail_first_frame_get(seq, frame_step, view_area);
|
||||
while ((timeline_frame < upper_thumb_bound) & !*stop) {
|
||||
ImBuf *ibuf = seq_cache_get(
|
||||
context, seq_orig, round_fl_to_int(start_frame), SEQ_CACHE_STORE_THUMBNAIL);
|
||||
context, seq_orig, round_fl_to_int(timeline_frame), SEQ_CACHE_STORE_THUMBNAIL);
|
||||
if (ibuf) {
|
||||
IMB_freeImBuf(ibuf);
|
||||
start_frame += frame_step;
|
||||
timeline_frame = SEQ_render_thumbnail_next_frame_get(seq, timeline_frame, frame_step);
|
||||
continue;
|
||||
}
|
||||
|
||||
ibuf = seq_get_uncached_thumbnail(context, &state, seq, round_fl_to_int(start_frame));
|
||||
ibuf = seq_get_uncached_thumbnail(context, &state, seq, round_fl_to_int(timeline_frame));
|
||||
|
||||
if (ibuf) {
|
||||
seq_cache_thumbnail_put(context, seq_orig, round_fl_to_int(start_frame), ibuf, view_area);
|
||||
seq_cache_thumbnail_put(context, seq_orig, round_fl_to_int(timeline_frame), ibuf, view_area);
|
||||
IMB_freeImBuf(ibuf);
|
||||
seq_orig->flag &= ~SEQ_FLAG_SKIP_THUMBNAILS;
|
||||
}
|
||||
|
@ -2090,7 +2115,7 @@ void SEQ_render_thumbnails(const SeqRenderData *context,
|
|||
return;
|
||||
}
|
||||
|
||||
start_frame += frame_step;
|
||||
timeline_frame = SEQ_render_thumbnail_next_frame_get(seq, timeline_frame, frame_step);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue