diff --git a/source/blender/editors/space_sequencer/sequencer_intern.hh b/source/blender/editors/space_sequencer/sequencer_intern.hh index 193fa01fa90..553b4dba4f5 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.hh +++ b/source/blender/editors/space_sequencer/sequencer_intern.hh @@ -8,13 +8,20 @@ #pragma once +#include "BLI_map.hh" #include "BLI_utility_mixins.hh" #include "BLI_vector.hh" #include "BLI_vector_set.hh" + #include "DNA_sequence_types.h" -#include "ED_sequencer.hh" + #include "RNA_access.hh" +#include "GPU_immediate.hh" +#include "GPU_viewport.hh" + +#include "ED_sequencer.hh" + #include "sequencer_scopes.hh" /* Internal exports only. */ @@ -80,6 +87,41 @@ struct SeqChannelDrawContext { float scale; }; +struct StripDrawContext { + Sequence *seq; + /* Strip boundary in timeline space. Content start/end is clamped by left/right handle. */ + float content_start, content_end, bottom, top; + float left_handle, right_handle; /* Position in frames. */ + float strip_content_top; /* Position in timeline space without content and text overlay. */ + float handle_width; /* Width of strip handle in frames. */ + float strip_length; + + bool can_draw_text_overlay; + bool can_draw_strip_content; + bool strip_is_too_small; /* Shorthand for (!can_draw_text_overlay && !can_draw_strip_content). */ + bool is_active_strip; + bool is_single_image; /* Strip has single frame of content. */ + bool show_strip_color_tag; + bool missing_data_block; + bool missing_media; +}; + +struct TimelineDrawContext { + const bContext *C; + ARegion *region; + Scene *scene; + SpaceSeq *sseq; + View2D *v2d; + Editing *ed; + ListBase *channels; + GPUViewport *viewport; + GPUFrameBuffer *framebuffer_overlay; + float pixelx, pixely; /* Width and height of pixel in timeline space. */ + blender::Map retiming_selection; + + SeqQuadsBatch *quads; +}; + /* `sequencer_timeline_draw.cc` */ void draw_timeline_seq(const bContext *C, ARegion *region); @@ -329,7 +371,12 @@ int sequencer_retiming_select_all_exec(bContext *C, wmOperator *op); int sequencer_retiming_box_select_exec(bContext *C, wmOperator *op); /* `sequencer_retiming_draw.cc` */ -void sequencer_draw_retiming(const bContext *C, SeqQuadsBatch *quads); +void sequencer_retiming_draw_continuity(const TimelineDrawContext *timeline_ctx, + const StripDrawContext &strip_ctx); +void sequencer_retiming_keys_draw(const TimelineDrawContext *timeline_ctx, + const StripDrawContext &strip_ctx); +void sequencer_retiming_speed_draw(const TimelineDrawContext *timeline_ctx, + const StripDrawContext &strip_ctx); SeqRetimingKey *try_to_realize_virtual_keys(const bContext *C, Sequence *seq, const int mval[2]); SeqRetimingKey *retiming_mousover_key_get(const bContext *C, const int mval[2], Sequence **r_seq); int left_fake_key_frame_get(const bContext *C, const Sequence *seq); diff --git a/source/blender/editors/space_sequencer/sequencer_retiming_draw.cc b/source/blender/editors/space_sequencer/sequencer_retiming_draw.cc index 226afd3cea4..570047e7e2c 100644 --- a/source/blender/editors/space_sequencer/sequencer_retiming_draw.cc +++ b/source/blender/editors/space_sequencer/sequencer_retiming_draw.cc @@ -19,7 +19,6 @@ #include "BLF_api.hh" #include "GPU_batch.hh" -#include "GPU_immediate.hh" #include "GPU_state.hh" #include "WM_api.hh" @@ -227,18 +226,36 @@ SeqRetimingKey *retiming_mousover_key_get(const bContext *C, const int mval[2], return nullptr; } +static bool can_draw_retiming(const TimelineDrawContext *timeline_ctx, + const StripDrawContext &strip_ctx) +{ + if (timeline_ctx->ed == nullptr) { + return false; + } + + if (!retiming_keys_are_visible(timeline_ctx->sseq)) { + return false; + } + + if (!SEQ_retiming_is_allowed(strip_ctx.seq)) { + return false; + } + + return true; +} + /* -------------------------------------------------------------------- */ /** \name Retiming Key * \{ */ -static void retime_key_draw(const bContext *C, - const Sequence *seq, +static void retime_key_draw(const TimelineDrawContext *timeline_ctx, + const StripDrawContext &strip_ctx, const SeqRetimingKey *key, - const KeyframeShaderBindings &sh_bindings, - const blender::Map &selection) + const KeyframeShaderBindings &sh_bindings) { - const Scene *scene = CTX_data_scene(C); - const View2D *v2d = UI_view2d_fromcontext(C); + const Scene *scene = timeline_ctx->scene; + const View2D *v2d = timeline_ctx->v2d; + Sequence *seq = strip_ctx.seq; const float key_x = key_x_get(scene, seq, key); const rctf strip_box = strip_box_get(scene, v2d, seq); @@ -254,17 +271,14 @@ static void retime_key_draw(const bContext *C, key_type = BEZT_KEYTYPE_MOVEHOLD; } - const bool is_selected = selection.contains(const_cast(key)); + const bool is_selected = timeline_ctx->retiming_selection.contains( + const_cast(key)); const int size = KEY_SIZE; const float bottom = KEY_CENTER; /* Ensure, that key is always inside of strip. */ - const float right_pos_max = UI_view2d_view_to_region_x( - v2d, SEQ_time_right_handle_frame_get(scene, seq)) - - (size / 2); - const float left_pos_min = UI_view2d_view_to_region_x( - v2d, SEQ_time_left_handle_frame_get(scene, seq)) + - (size / 2); + const float right_pos_max = UI_view2d_view_to_region_x(v2d, strip_ctx.right_handle) - (size / 2); + const float left_pos_min = UI_view2d_view_to_region_x(v2d, strip_ctx.left_handle) + (size / 2); float key_position = UI_view2d_view_to_region_x(v2d, key_x); CLAMP(key_position, left_pos_min, right_pos_max); const float alpha = SEQ_retiming_data_is_editable(seq) ? 1.0f : 0.3f; @@ -281,134 +295,115 @@ static void retime_key_draw(const bContext *C, 0); } -static void draw_continuity(const bContext *C, - const Sequence *seq, - const SeqRetimingKey *key, - const blender::Map &selection, - SeqQuadsBatch *quads) +void sequencer_retiming_draw_continuity(const TimelineDrawContext *timeline_ctx, + const StripDrawContext &strip_ctx) { - const View2D *v2d = UI_view2d_fromcontext(C); - const Scene *scene = CTX_data_scene(C); - - if (key_x_get(scene, seq, key) == SEQ_time_left_handle_frame_get(scene, seq) || - key->strip_frame_index == 0) - { + if (!can_draw_retiming(timeline_ctx, strip_ctx)) { return; } - const float left_handle_position = UI_view2d_view_to_region_x( - v2d, SEQ_time_left_handle_frame_get(scene, seq)); - const float right_handle_position = UI_view2d_view_to_region_x( - v2d, SEQ_time_right_handle_frame_get(scene, seq)); + wmOrtho2_region_pixelspace(timeline_ctx->region); - float key_position = UI_view2d_view_to_region_x(v2d, key_x_get(scene, seq, key)); - float prev_key_position = UI_view2d_view_to_region_x(v2d, key_x_get(scene, seq, key - 1)); - prev_key_position = max_ff(prev_key_position, left_handle_position); - key_position = min_ff(key_position, right_handle_position); + const Sequence *seq = strip_ctx.seq; + const View2D *v2d = timeline_ctx->v2d; + const Scene *scene = timeline_ctx->scene; + const float left_handle_position = UI_view2d_view_to_region_x(v2d, strip_ctx.left_handle); + const float right_handle_position = UI_view2d_view_to_region_x(v2d, strip_ctx.right_handle); - const int size = KEY_SIZE; - const float y_center = KEY_CENTER; + for (const SeqRetimingKey &key : SEQ_retiming_keys_get(seq)) { + if (key_x_get(scene, seq, &key) == strip_ctx.left_handle || key.strip_frame_index == 0) { + continue; + } - const float width_fac = 0.5f; - const float bottom = y_center - size * width_fac; - const float top = y_center + size * width_fac; + float key_position = UI_view2d_view_to_region_x(v2d, key_x_get(scene, seq, &key)); + float prev_key_position = UI_view2d_view_to_region_x(v2d, key_x_get(scene, seq, &key - 1)); + prev_key_position = max_ff(prev_key_position, left_handle_position); + key_position = min_ff(key_position, right_handle_position); - uchar color[4]; - if (SEQ_retiming_data_is_editable(seq) && - (selection.contains(const_cast(key)) || - selection.contains(const_cast(key - 1)))) - { - color[0] = 166; - color[1] = 127; - color[2] = 51; - color[3] = 255; + const int size = KEY_SIZE; + const float y_center = KEY_CENTER; + + const float width_fac = 0.5f; + const float bottom = y_center - size * width_fac; + const float top = y_center + size * width_fac; + + uchar color[4]; + if (SEQ_retiming_data_is_editable(seq) && + (timeline_ctx->retiming_selection.contains(const_cast(&key)) || + timeline_ctx->retiming_selection.contains(const_cast(&key - 1)))) + { + color[0] = 166; + color[1] = 127; + color[2] = 51; + color[3] = 255; + } + else { + color[0] = 0; + color[1] = 0; + color[2] = 0; + color[3] = 25; + } + timeline_ctx->quads->add_quad(prev_key_position, bottom, key_position, top, color); } - else { - color[0] = 0; - color[1] = 0; - color[2] = 0; - color[3] = 25; - } - quads->add_quad(prev_key_position, bottom, key_position, top, color); +} + +static SeqRetimingKey retiming_key_init(const Scene *scene, + const Sequence *seq, + int timeline_frame) +{ + SeqRetimingKey fake_key; + fake_key.strip_frame_index = (timeline_frame - SEQ_time_start_frame_get(seq)) * + SEQ_time_media_playback_rate_factor_get(scene, seq); + fake_key.flag = 0; + return fake_key; } /* If there are no keys, draw fake keys and create real key when they are selected. */ /* TODO: would be nice to draw continuity between fake keys. */ -static bool fake_keys_draw(const bContext *C, - Sequence *seq, - const KeyframeShaderBindings &sh_bindings, - const blender::Map &selection) +static bool fake_keys_draw(const TimelineDrawContext *timeline_ctx, + const StripDrawContext &strip_ctx, + const KeyframeShaderBindings &sh_bindings) { + const Sequence *seq = strip_ctx.seq; + const Scene *scene = timeline_ctx->scene; + if (!SEQ_retiming_is_active(seq) && !SEQ_retiming_data_is_editable(seq)) { return false; } - const Scene *scene = CTX_data_scene(C); - const int left_key_frame = left_fake_key_frame_get(C, seq); - int right_key_frame = right_fake_key_frame_get(C, seq); - + const int left_key_frame = left_fake_key_frame_get(timeline_ctx->C, seq); if (SEQ_retiming_key_get_by_timeline_frame(scene, seq, left_key_frame) == nullptr) { - SeqRetimingKey fake_key; - fake_key.strip_frame_index = (left_key_frame - SEQ_time_start_frame_get(seq)) * - SEQ_time_media_playback_rate_factor_get(scene, seq); - fake_key.flag = 0; - retime_key_draw(C, seq, &fake_key, sh_bindings, selection); + SeqRetimingKey fake_key = retiming_key_init(scene, seq, left_key_frame); + retime_key_draw(timeline_ctx, strip_ctx, &fake_key, sh_bindings); } + int right_key_frame = right_fake_key_frame_get(timeline_ctx->C, seq); if (SEQ_retiming_key_get_by_timeline_frame(scene, seq, right_key_frame) == nullptr) { /* `key_x_get()` compensates 1 frame offset of last key, however this can not * be conveyed via `fake_key` alone. Therefore the same offset must be emulated. */ - if (SEQ_time_right_handle_frame_get(scene, seq) >= SEQ_time_content_end_frame_get(scene, seq)) - { + if (strip_ctx.right_handle >= SEQ_time_content_end_frame_get(scene, seq)) { right_key_frame += 1; } - - SeqRetimingKey fake_key; - fake_key.strip_frame_index = (right_key_frame - SEQ_time_start_frame_get(seq)) * - SEQ_time_media_playback_rate_factor_get(scene, seq); - fake_key.flag = 0; - retime_key_draw(C, seq, &fake_key, sh_bindings, selection); + SeqRetimingKey fake_key = retiming_key_init(scene, seq, right_key_frame); + retime_key_draw(timeline_ctx, strip_ctx, &fake_key, sh_bindings); } return true; } -static void retime_keys_draw(const bContext *C, SeqQuadsBatch *quads) +void sequencer_retiming_keys_draw(const TimelineDrawContext *timeline_ctx, + const StripDrawContext &strip_ctx) { - const Scene *scene = CTX_data_scene(C); - if (scene->ed == nullptr) { + if (!can_draw_retiming(timeline_ctx, strip_ctx)) { return; } - if (!retiming_keys_are_visible(CTX_wm_space_seq(C))) { - return; - } + wmOrtho2_region_pixelspace(timeline_ctx->region); - /* Get the selection here once, for faster "is key selected?" lookups later. */ - blender::Map selection = SEQ_retiming_selection_get(scene->ed); - - wmOrtho2_region_pixelspace(CTX_wm_region(C)); - - blender::Vector strips = sequencer_visible_strips_get(C); - - /* Draw all continuity sections. */ - GPU_blend(GPU_BLEND_ALPHA); - for (Sequence *seq : strips) { - if (!SEQ_retiming_is_allowed(seq)) { - continue; - } - - for (const SeqRetimingKey &key : SEQ_retiming_keys_get(seq)) { - draw_continuity(C, seq, &key, selection, quads); - } - } - quads->draw(); - - /* Draw all keys. */ - const View2D *v2d = UI_view2d_fromcontext(C); + const View2D *v2d = timeline_ctx->v2d; + const Sequence *seq = strip_ctx.seq; GPUVertFormat *format = immVertexFormat(); KeyframeShaderBindings sh_bindings; - sh_bindings.pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); sh_bindings.size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); sh_bindings.color_id = GPU_vertformat_attr_add( @@ -426,32 +421,26 @@ static void retime_keys_draw(const bContext *C, SeqQuadsBatch *quads) int point_counter = 0; immBeginAtMost(GPU_PRIM_POINTS, MAX_KEYS_IN_BATCH); - for (Sequence *seq : strips) { - if (!SEQ_retiming_is_allowed(seq)) { - continue; - } + if (fake_keys_draw(timeline_ctx, strip_ctx, sh_bindings)) { + point_counter += 2; + } - if (fake_keys_draw(C, seq, sh_bindings, selection)) { - point_counter += 2; - } + for (const SeqRetimingKey &key : SEQ_retiming_keys_get(seq)) { + retime_key_draw(timeline_ctx, strip_ctx, &key, sh_bindings); + point_counter++; - for (const SeqRetimingKey &key : SEQ_retiming_keys_get(seq)) { - retime_key_draw(C, seq, &key, sh_bindings, selection); - point_counter++; - - /* Next key plus possible two fake keys for next sequence would need at - * most 3 points, so restart the batch if we're close to that. */ - if (point_counter + 3 >= MAX_KEYS_IN_BATCH) { - immEnd(); - immBeginAtMost(GPU_PRIM_POINTS, MAX_KEYS_IN_BATCH); - point_counter = 0; - } + /* Next key plus possible two fake keys for next sequence would need at + * most 3 points, so restart the batch if we're close to that. */ + if (point_counter + 3 >= MAX_KEYS_IN_BATCH) { + immEnd(); + immBeginAtMost(GPU_PRIM_POINTS, MAX_KEYS_IN_BATCH); + point_counter = 0; } } + immEnd(); GPU_program_point_size(false); immUnbindProgram(); - GPU_blend(GPU_BLEND_NONE); } /** \} */ @@ -480,45 +469,44 @@ static size_t label_str_get(const Sequence *seq, r_label_str, label_str_maxncpy, "%d%%", round_fl_to_int(speed * 100.0f)); } -static bool label_rect_get(const bContext *C, - const Sequence *seq, +static bool label_rect_get(const TimelineDrawContext *timeline_ctx, + const StripDrawContext &strip_ctx, const SeqRetimingKey *key, const char *label_str, const size_t label_len, rctf *rect) { - const Scene *scene = CTX_data_scene(C); + const bContext *C = timeline_ctx->C; + const Scene *scene = timeline_ctx->scene; const SeqRetimingKey *next_key = key + 1; const float width = pixels_to_view_width(C, BLF_width(BLF_default(), label_str, label_len)); const float height = pixels_to_view_height(C, BLF_height(BLF_default(), label_str, label_len)); - - const float xmin = max_ff(SEQ_time_left_handle_frame_get(scene, seq), - key_x_get(scene, seq, key)); - const float xmax = min_ff(SEQ_time_right_handle_frame_get(scene, seq), - key_x_get(scene, seq, next_key)); + const float xmin = max_ff(strip_ctx.left_handle, key_x_get(scene, strip_ctx.seq, key)); + const float xmax = min_ff(strip_ctx.right_handle, key_x_get(scene, strip_ctx.seq, next_key)); rect->xmin = (xmin + xmax - width) / 2; rect->xmax = rect->xmin + width; - rect->ymin = strip_y_rescale(seq, 0) + pixels_to_view_height(C, 5); + rect->ymin = strip_y_rescale(strip_ctx.seq, 0) + pixels_to_view_height(C, 5); rect->ymax = rect->ymin + height; return width < xmax - xmin - pixels_to_view_width(C, KEY_SIZE); } -static void retime_speed_text_draw(const bContext *C, - const Sequence *seq, +static void retime_speed_text_draw(const TimelineDrawContext *timeline_ctx, + const StripDrawContext &strip_ctx, const SeqRetimingKey *key) { + const Sequence *seq = strip_ctx.seq; + const Scene *scene = timeline_ctx->scene; + if (SEQ_retiming_is_last_key(seq, key)) { return; } - const Scene *scene = CTX_data_scene(C); - const int start_frame = SEQ_time_left_handle_frame_get(scene, seq); - const int end_frame = SEQ_time_right_handle_frame_get(scene, seq); - const SeqRetimingKey *next_key = key + 1; - if (key_x_get(scene, seq, next_key) < start_frame || key_x_get(scene, seq, key) > end_frame) { + if (key_x_get(scene, seq, next_key) < strip_ctx.left_handle || + key_x_get(scene, seq, key) > strip_ctx.right_handle) + { return; /* Label out of strip bounds. */ } @@ -526,7 +514,7 @@ static void retime_speed_text_draw(const bContext *C, rctf label_rect; size_t label_len = label_str_get(seq, key, label_str, sizeof(label_str)); - if (!label_rect_get(C, seq, key, label_str, label_len, &label_rect)) { + if (!label_rect_get(timeline_ctx, strip_ctx, key, label_str, label_len, &label_rect)) { return; /* Not enough space to draw the label. */ } @@ -537,44 +525,21 @@ static void retime_speed_text_draw(const bContext *C, } UI_view2d_text_cache_add( - UI_view2d_fromcontext(C), label_rect.xmin, label_rect.ymin, label_str, label_len, col); + timeline_ctx->v2d, label_rect.xmin, label_rect.ymin, label_str, label_len, col); } -static void retime_speed_draw(const bContext *C) +void sequencer_retiming_speed_draw(const TimelineDrawContext *timeline_ctx, + const StripDrawContext &strip_ctx) { - const Scene *scene = CTX_data_scene(C); - if (scene->ed == nullptr) { + if (!can_draw_retiming(timeline_ctx, strip_ctx)) { return; } - if (!retiming_keys_are_visible(CTX_wm_space_seq(C))) { - return; + for (const SeqRetimingKey &key : SEQ_retiming_keys_get(strip_ctx.seq)) { + retime_speed_text_draw(timeline_ctx, strip_ctx, &key); } - const View2D *v2d = UI_view2d_fromcontext(C); - - wmOrtho2_region_pixelspace(CTX_wm_region(C)); - GPU_blend(GPU_BLEND_ALPHA); - GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - - for (const Sequence *seq : sequencer_visible_strips_get(C)) { - for (const SeqRetimingKey &key : SEQ_retiming_keys_get(seq)) { - retime_speed_text_draw(C, seq, &key); - } - } - - immUnbindProgram(); - GPU_blend(GPU_BLEND_NONE); - - UI_view2d_text_cache_draw(CTX_wm_region(C)); - UI_view2d_view_ortho(v2d); /* 'UI_view2d_text_cache_draw()' messes up current view. */ + UI_view2d_view_ortho(timeline_ctx->v2d); } /** \} */ - -void sequencer_draw_retiming(const bContext *C, SeqQuadsBatch *quads) -{ - retime_keys_draw(C, quads); - retime_speed_draw(C); -} diff --git a/source/blender/editors/space_sequencer/sequencer_timeline_draw.cc b/source/blender/editors/space_sequencer/sequencer_timeline_draw.cc index 10a8140ad6c..4632bef5cd0 100644 --- a/source/blender/editors/space_sequencer/sequencer_timeline_draw.cc +++ b/source/blender/editors/space_sequencer/sequencer_timeline_draw.cc @@ -27,9 +27,6 @@ #include "BKE_global.hh" #include "BKE_sound.h" -#include "GPU_immediate.hh" -#include "GPU_viewport.hh" - #include "ED_anim_api.hh" #include "ED_markers.hh" #include "ED_mask.hh" @@ -44,6 +41,7 @@ #include "SEQ_prefetch.hh" #include "SEQ_relations.hh" #include "SEQ_render.hh" +#include "SEQ_retiming.hh" #include "SEQ_select.hh" #include "SEQ_sequencer.hh" #include "SEQ_time.hh" @@ -73,40 +71,6 @@ using namespace blender::ed::seq; constexpr float MISSING_ICON_SIZE = 12.0f; -struct StripDrawContext { - Sequence *seq; - /* Strip boundary in timeline space. Content start/end is clamped by left/right handle. */ - float content_start, content_end, bottom, top; - float left_handle, right_handle; /* Position in frames. */ - float strip_content_top; /* Position in timeline space without content and text overlay. */ - float handle_width; /* Width of strip handle in frames. */ - float strip_length; - - bool can_draw_text_overlay; - bool can_draw_strip_content; - bool strip_is_too_small; /* Shorthand for (!can_draw_text_overlay && !can_draw_strip_content). */ - bool is_active_strip; - bool is_single_image; /* Strip has single frame of content. */ - bool show_strip_color_tag; - bool missing_data_block; - bool missing_media; -}; - -struct TimelineDrawContext { - const bContext *C; - ARegion *region; - Scene *scene; - SpaceSeq *sseq; - View2D *v2d; - Editing *ed; - ListBase *channels; - GPUViewport *viewport; - GPUFrameBuffer *framebuffer_overlay; - float pixelx, pixely; /* Width and height of pixel in timeline space. */ - - SeqQuadsBatch *quads; -}; - Vector sequencer_visible_strips_get(const bContext *C) { return sequencer_visible_strips_get(CTX_data_scene(C), UI_view2d_fromcontext(C)); @@ -158,6 +122,8 @@ static TimelineDrawContext timeline_draw_context_get(const bContext *C, SeqQuads ctx.pixely = BLI_rctf_size_y(&ctx.v2d->cur) / BLI_rcti_size_y(&ctx.v2d->mask); ctx.pixelx = BLI_rctf_size_x(&ctx.v2d->cur) / BLI_rcti_size_x(&ctx.v2d->mask); + ctx.retiming_selection = SEQ_retiming_selection_get(ctx.ed); + ctx.quads = quads_batch; return ctx; @@ -1515,7 +1481,7 @@ static void draw_seq_strips(TimelineDrawContext *timeline_ctx, } timeline_ctx->quads->draw(); - /* Draw all thumbnails. */ + /* Draw all thumbnails and retiming continuity. */ GPU_blend(GPU_BLEND_ALPHA); for (const StripDrawContext &strip_ctx : strips) { draw_seq_strip_thumbnail(timeline_ctx->v2d, @@ -1528,7 +1494,9 @@ static void draw_seq_strips(TimelineDrawContext *timeline_ctx, timeline_ctx->pixelx, timeline_ctx->pixely, round_radius); + sequencer_retiming_draw_continuity(timeline_ctx, strip_ctx); } + timeline_ctx->quads->draw(); /* Draw parts of strips above thumbnails. */ GPU_blend(GPU_BLEND_ALPHA); @@ -1539,7 +1507,10 @@ static void draw_seq_strips(TimelineDrawContext *timeline_ctx, draw_handle_transform_text(timeline_ctx, &strip_ctx, SEQ_HANDLE_LEFT); draw_handle_transform_text(timeline_ctx, &strip_ctx, SEQ_HANDLE_RIGHT); draw_seq_text_overlay(timeline_ctx, &strip_ctx); + sequencer_retiming_keys_draw(timeline_ctx, strip_ctx); + sequencer_retiming_speed_draw(timeline_ctx, strip_ctx); } + timeline_ctx->quads->draw(); draw_strips_foreground(timeline_ctx, strips_batch, strips); @@ -1919,7 +1890,6 @@ void draw_timeline_seq(const bContext *C, ARegion *region) draw_timeline_backdrop(&ctx); draw_timeline_sfra_efra(&ctx); draw_seq_strips(&ctx, strips_batch); - sequencer_draw_retiming(C, &quads_batch); draw_timeline_markers(&ctx); UI_view2d_view_ortho(ctx.v2d); ANIM_draw_previewrange(C, ctx.v2d, 1);