Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/space_sequencer/sequencer_thumbnails.c
| Show First 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | static void thumbnail_endjob(void *data) | ||||
| WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, tj->scene); | WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, tj->scene); | ||||
| } | } | ||||
| static bool check_seq_need_thumbnails(Sequence *seq, rctf *view_area) | static bool check_seq_need_thumbnails(Sequence *seq, rctf *view_area) | ||||
| { | { | ||||
| if (seq->type != SEQ_TYPE_MOVIE && seq->type != SEQ_TYPE_IMAGE) { | if (seq->type != SEQ_TYPE_MOVIE && seq->type != SEQ_TYPE_IMAGE) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (min_ii(seq->startdisp, seq->start) > view_area->xmax) { | if (seq->startdisp > view_area->xmax) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (max_ii(seq->enddisp, seq->start + seq->len) < view_area->xmin) { | if (seq->enddisp < view_area->xmin) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (seq->machine + 1.0f < view_area->ymin) { | if (seq->machine + 1.0f < view_area->ymin) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (seq->machine > view_area->ymax) { | if (seq->machine > view_area->ymax) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| if ((G.moving & G_TRANSFORM_SEQ) != 0 && (seq->flag & SEQ_LEFTSEL | SEQ_RIGHTSEL) == 0) { | |||||
| return false; | |||||
| } | |||||
| return true; | return true; | ||||
| } | } | ||||
| static void seq_get_thumb_image_dimensions(Sequence *seq, | static void seq_get_thumb_image_dimensions(Sequence *seq, | ||||
| float pixelx, | float pixelx, | ||||
| float pixely, | float pixely, | ||||
| float *r_thumb_width, | float *r_thumb_width, | ||||
| float *r_thumb_height, | float *r_thumb_height, | ||||
| Show All 28 Lines | static void seq_get_thumb_image_dimensions(Sequence *seq, | ||||
| *r_thumb_height = thumb_height; | *r_thumb_height = thumb_height; | ||||
| *r_image_width = image_width; | *r_image_width = image_width; | ||||
| *r_image_height = image_height; | *r_image_height = image_height; | ||||
| *r_thumb_width = thumb_width; | *r_thumb_width = thumb_width; | ||||
| } | } | ||||
| static float seq_thumbnail_get_start_frame(Sequence *seq, float frame_step, rctf *view_area) | 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) { | if (seq->startstill) { | ||||
| return seq->start; | return seq->start; | ||||
| } | } | ||||
| return seq->startdisp; | |||||
| /* 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, | static void thumbnail_start_job(void *data, | ||||
| short *stop, | short *stop, | ||||
| short *UNUSED(do_update), | short *UNUSED(do_update), | ||||
| float *UNUSED(progress)) | float *UNUSED(progress)) | ||||
| { | { | ||||
| ThumbnailDrawJob *tj = data; | ThumbnailDrawJob *tj = data; | ||||
| float start_frame, frame_step; | float start_frame, frame_step; | ||||
| GHashIterator gh_iter; | GHashIterator gh_iter; | ||||
| bool transform_update = (G.moving & G_TRANSFORM_SEQ) != 0; | |||||
| /* First pass: render visible images. */ | /* First pass: render visible images. */ | ||||
| BLI_ghashIterator_init(&gh_iter, tj->sequences_ghash); | BLI_ghashIterator_init(&gh_iter, tj->sequences_ghash); | ||||
| while (!BLI_ghashIterator_done(&gh_iter) & !*stop) { | while (!BLI_ghashIterator_done(&gh_iter) & !*stop) { | ||||
| Sequence *seq_orig = BLI_ghashIterator_getKey(&gh_iter); | Sequence *seq_orig = BLI_ghashIterator_getKey(&gh_iter); | ||||
| ThumbDataItem *val = BLI_ghash_lookup(tj->sequences_ghash, seq_orig); | ThumbDataItem *val = BLI_ghash_lookup(tj->sequences_ghash, seq_orig); | ||||
| if (check_seq_need_thumbnails(seq_orig, tj->view_area)) { | if (check_seq_need_thumbnails(seq_orig, tj->view_area)) { | ||||
| seq_get_thumb_image_dimensions( | seq_get_thumb_image_dimensions( | ||||
| val->seq_dupli, tj->pixelx, tj->pixely, &frame_step, NULL, NULL, NULL); | 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); | start_frame = seq_thumbnail_get_start_frame(seq_orig, frame_step, tj->view_area); | ||||
| SEQ_render_thumbnails( | SEQ_render_thumbnails(&tj->context, | ||||
| &tj->context, val->seq_dupli, seq_orig, start_frame, frame_step, tj->view_area, stop); | val->seq_dupli, | ||||
| seq_orig, | |||||
| start_frame, | |||||
| frame_step, | |||||
| tj->view_area, | |||||
| transform_update, | |||||
| stop); | |||||
| SEQ_relations_sequence_free_anim(val->seq_dupli); | SEQ_relations_sequence_free_anim(val->seq_dupli); | ||||
| } | } | ||||
| BLI_ghashIterator_step(&gh_iter); | BLI_ghashIterator_step(&gh_iter); | ||||
| } | } | ||||
| /* Skip second pass when moving strips - first/last thumbnails are prioritized. */ | |||||
| if (transform_update) { | |||||
| return; | |||||
| } | |||||
| /* Second pass: render "guaranteed" set of images. */ | /* Second pass: render "guaranteed" set of images. */ | ||||
| BLI_ghashIterator_init(&gh_iter, tj->sequences_ghash); | BLI_ghashIterator_init(&gh_iter, tj->sequences_ghash); | ||||
| while (!BLI_ghashIterator_done(&gh_iter) & !*stop) { | while (!BLI_ghashIterator_done(&gh_iter) & !*stop) { | ||||
| Sequence *seq_orig = BLI_ghashIterator_getKey(&gh_iter); | Sequence *seq_orig = BLI_ghashIterator_getKey(&gh_iter); | ||||
| ThumbDataItem *val = BLI_ghash_lookup(tj->sequences_ghash, seq_orig); | ThumbDataItem *val = BLI_ghash_lookup(tj->sequences_ghash, seq_orig); | ||||
| if (check_seq_need_thumbnails(seq_orig, tj->view_area)) { | if (check_seq_need_thumbnails(seq_orig, tj->view_area)) { | ||||
| seq_get_thumb_image_dimensions( | seq_get_thumb_image_dimensions( | ||||
| ▲ Show 20 Lines • Show All 191 Lines • ▼ Show 20 Lines | while (!BLI_gsetIterator_done(&gset_iter)) { | ||||
| } | } | ||||
| BLI_gsetIterator_step(&gset_iter); | BLI_gsetIterator_step(&gset_iter); | ||||
| } | } | ||||
| return best_frame; | return best_frame; | ||||
| } | } | ||||
| static int sequencer_thumbnail_closest_guaranteed_frame_get(Sequence *seq, int timeline_frame) | static int sequencer_thumbnail_closest_guaranteed_frame_get(Sequence *seq, int timeline_frame) | ||||
| { | { | ||||
| if (timeline_frame <= seq->startdisp) { | |||||
| return seq->startdisp; | |||||
| } | |||||
| /* Set of "guaranteed" thumbnails. */ | /* Set of "guaranteed" thumbnails. */ | ||||
| const int frame_index = timeline_frame - seq->startdisp; | |||||
| const int frame_step = SEQ_render_thumbnails_guaranteed_set_frame_step_get(seq); | const int frame_step = SEQ_render_thumbnails_guaranteed_set_frame_step_get(seq); | ||||
| const int relative_base_frame = round_fl_to_int((frame_index / (float)frame_step)) * frame_step; | const int frame_index = seq->start - timeline_frame; | ||||
| const int nearest_guaranted_absolute_frame = relative_base_frame + seq->startdisp; | const int steps = round_fl_to_int((frame_index + frame_step * 0.5f) / frame_step); | ||||
| return nearest_guaranted_absolute_frame; | return seq->start + steps * frame_step; | ||||
| } | } | ||||
| static ImBuf *sequencer_thumbnail_closest_from_memory(const SeqRenderData *context, | static ImBuf *sequencer_thumbnail_closest_from_memory(const SeqRenderData *context, | ||||
| Sequence *seq, | Sequence *seq, | ||||
| int timeline_frame, | int timeline_frame, | ||||
| GSet *previously_displayed, | GSet *previously_displayed, | ||||
| rcti *crop, | rcti *crop, | ||||
| bool clipped) | bool clipped) | ||||
| ▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | void draw_seq_strip_thumbnail(View2D *v2d, | ||||
| float thumb_x_start = seq_thumbnail_get_start_frame(seq, thumb_width, &v2d->cur); | float thumb_x_start = seq_thumbnail_get_start_frame(seq, thumb_width, &v2d->cur); | ||||
| float thumb_x_end; | float thumb_x_end; | ||||
| while (thumb_x_start + thumb_width < v2d->cur.xmin) { | while (thumb_x_start + thumb_width < v2d->cur.xmin) { | ||||
| thumb_x_start += thumb_width; | 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); | 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 | /* Cleanup thumbnail list outside of rendered range, which is cleaned up one by one to prevent | ||||
| * flickering after zooming. */ | * flickering after zooming. */ | ||||
| if (!sequencer_thumbnail_v2d_is_navigating(C)) { | 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, thumb_x_start); | ||||
| } | } | ||||
| /* Start drawing. */ | /* Start drawing. */ | ||||
| Show All 33 Lines | while (thumb_x_start < upper_thumb_bound) { | ||||
| } | } | ||||
| BLI_rcti_init(&crop, (int)(cropx_min), (int)cropx_max, 0, (int)(image_height)-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); | int timeline_frame = round_fl_to_int(thumb_x_start); | ||||
| /* Get the image. */ | /* Get the image. */ | ||||
| ImBuf *ibuf = SEQ_get_thumbnail(&context, seq, timeline_frame, &crop, clipped); | ImBuf *ibuf = SEQ_get_thumbnail(&context, seq, timeline_frame, &crop, clipped); | ||||
| if (!ibuf) { | /* Handle of this strip is being moved. Job should update thumbnail quickly, but we have no | ||||
| * idea about this. Best approach seems to be to search for thumbnail frame by frame. */ | |||||
| if (!ibuf && timeline_frame == seq->startdisp && (G.moving & G_TRANSFORM_SEQ) != 0 && | |||||
| (seq->flag & SEQ_LEFTSEL | SEQ_RIGHTSEL) != 0) { | |||||
| /* When moving handle, start job only when first thumbnail is missing. */ | |||||
| sequencer_thumbnail_start_job_if_necessary(C, scene->ed, v2d, true); | sequencer_thumbnail_start_job_if_necessary(C, scene->ed, v2d, true); | ||||
| for (int offset = 1; offset < (pixelx * 100); offset++) { | |||||
| ibuf = SEQ_get_thumbnail(&context, seq, timeline_frame - offset, &crop, clipped); | |||||
| if (ibuf != NULL) { | |||||
| printf("Frame update found - req: %d, found: %d\n", | |||||
| timeline_frame, | |||||
| timeline_frame - offset); | |||||
| break; | |||||
| } | |||||
| ibuf = SEQ_get_thumbnail(&context, seq, timeline_frame + offset, &crop, clipped); | |||||
| if (ibuf != NULL) { | |||||
| printf("Frame update found - req: %d, found: %d\n", | |||||
| timeline_frame, | |||||
| timeline_frame + offset); | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| if (!ibuf) { | |||||
| if ((G.moving & G_TRANSFORM_SEQ) == 0 || (seq->flag & SEQ_LEFTSEL | SEQ_RIGHTSEL) == 0) { | |||||
| /* Start job only when not not moving handle. Otherwise only first thumbnail would be | |||||
| * updated. */ | |||||
| sequencer_thumbnail_start_job_if_necessary(C, scene->ed, v2d, true); | |||||
| } | |||||
| ibuf = sequencer_thumbnail_closest_from_memory( | ibuf = sequencer_thumbnail_closest_from_memory( | ||||
| &context, seq, timeline_frame, last_displayed_thumbnails, &crop, clipped); | &context, seq, timeline_frame, last_displayed_thumbnails, &crop, clipped); | ||||
| } | } | ||||
| /* Store recently rendered frames, so they can be reused when zooming. */ | /* Store recently rendered frames, so they can be reused when zooming. */ | ||||
| else if (!sequencer_thumbnail_v2d_is_navigating(C)) { | else if (!sequencer_thumbnail_v2d_is_navigating(C)) { | ||||
| /* Clear images in frame range occupied by new thumbnail. */ | /* Clear images in frame range occupied by new thumbnail. */ | ||||
| last_displayed_thumbnails_list_cleanup( | last_displayed_thumbnails_list_cleanup( | ||||
| last_displayed_thumbnails, thumb_x_start, thumb_x_end); | last_displayed_thumbnails, thumb_x_start, thumb_x_end); | ||||
| ▲ Show 20 Lines • Show All 44 Lines • Show Last 20 Lines | |||||