Fix: VSE: Overlap after moving a retiming key was not handled

Moving a strip retiming key at the end of a strip, so that a strip
overlaps another one would leave them overlapped. The expected
behavior is that it acts according to the Overlap Mode, like it does
when moving a strip.

Co-authored-by: Richard Antalik <richardantalik@gmail.com>
Pull Request: https://projects.blender.org/blender/blender/pulls/124424
This commit is contained in:
il4n 2024-07-10 02:21:14 +02:00 committed by Richard Antalik
parent b2e3b6c393
commit e13b2f3774
6 changed files with 78 additions and 37 deletions

View File

@ -1242,36 +1242,21 @@ static void draw_seq_timeline_channels(TimelineDrawContext *ctx)
* sure that visually selected are always "on top" of others. It matters
* while selection is being dragged over other strips. */
static void visible_strips_ordered_get(TimelineDrawContext *timeline_ctx,
Vector<StripDrawContext> &r_unselected,
Vector<StripDrawContext> &r_selected)
Vector<StripDrawContext> &r_bottom_layer,
Vector<StripDrawContext> &r_top_layer)
{
Sequence *act_seq = SEQ_select_active_get(timeline_ctx->scene);
r_bottom_layer.clear();
r_top_layer.clear();
Vector<Sequence *> strips = sequencer_visible_strips_get(timeline_ctx->C);
r_unselected.clear();
r_selected.clear();
for (Sequence *seq : strips) {
/* Active will be added last. */
if (seq == act_seq) {
continue;
}
StripDrawContext strip_ctx = strip_draw_context_get(timeline_ctx, seq);
if ((seq->flag & SELECT) == 0) {
r_unselected.append(strip_ctx);
if ((seq->flag & SEQ_OVERLAP) == 0) {
r_bottom_layer.append(strip_ctx);
}
else {
r_selected.append(strip_ctx);
}
}
/* Add active, if any. */
if (act_seq) {
StripDrawContext strip_ctx = strip_draw_context_get(timeline_ctx, act_seq);
if ((act_seq->flag & SELECT) == 0) {
r_unselected.append(strip_ctx);
}
else {
r_selected.append(strip_ctx);
r_top_layer.append(strip_ctx);
}
}
}
@ -1407,18 +1392,26 @@ static void draw_strips_foreground(TimelineDrawContext *timeline_ctx,
* - Slightly lighter.
* - Red when overlapping with other strips. */
const eSeqOverlapMode overlap_mode = SEQ_tool_settings_overlap_mode_get(timeline_ctx->scene);
if ((G.moving & G_TRANSFORM_SEQ) && selected) {
if (G.moving & G_TRANSFORM_SEQ) {
if ((strip.seq->flag & SEQ_OVERLAP) && (overlap_mode != SEQ_OVERLAP_OVERWRITE)) {
col[0] = 255;
col[1] = col[2] = 33;
}
else {
else if (selected) {
UI_GetColorPtrShade3ubv(col, col, 70);
}
}
if (selected)
const bool overlaps = (strip.seq->flag & SEQ_OVERLAP) && (G.moving & G_TRANSFORM_SEQ);
if (overlaps) {
data.flags |= GPU_SEQ_FLAG_OVERLAP;
}
if (selected) {
data.flags |= GPU_SEQ_FLAG_SELECTED;
else if (active) {
}
else if (active && !overlaps) {
/* If the strips overlap when retiming, don't replace the red outline. */
/* A subtle highlight outline when active but not selected. */
UI_GetThemeColorShade3ubv(TH_SEQ_ACTIVE, -40, col);
data.flags |= GPU_SEQ_FLAG_ACTIVE;
@ -1525,10 +1518,10 @@ static void draw_seq_strips(TimelineDrawContext *timeline_ctx, StripsDrawBatch &
return;
}
Vector<StripDrawContext> unselected, selected;
visible_strips_ordered_get(timeline_ctx, unselected, selected);
draw_seq_strips(timeline_ctx, strips_batch, unselected);
draw_seq_strips(timeline_ctx, strips_batch, selected);
Vector<StripDrawContext> bottom_layer, top_layer;
visible_strips_ordered_get(timeline_ctx, bottom_layer, top_layer);
draw_seq_strips(timeline_ctx, strips_batch, bottom_layer);
draw_seq_strips(timeline_ctx, strips_batch, top_layer);
}
static void draw_timeline_sfra_efra(TimelineDrawContext *ctx)

View File

@ -24,6 +24,7 @@ struct TransData;
struct TransDataCurveHandleFlags;
struct TransInfo;
struct bContext;
struct Sequence;
struct TransConvertTypeInfo {
int flags; /* #eTFlag. */
@ -366,6 +367,8 @@ extern TransConvertTypeInfo TransConvertType_Sculpt;
extern TransConvertTypeInfo TransConvertType_Sequencer;
bool seq_transform_check_overlap(blender::Span<Sequence *> transformed_strips);
/* `transform_convert_sequencer_image.cc` */
extern TransConvertTypeInfo TransConvertType_SequencerImage;

View File

@ -286,7 +286,7 @@ static ListBase *seqbase_active_get(const TransInfo *t)
return SEQ_active_seqbase_get(ed);
}
static bool seq_transform_check_overlap(blender::Span<Sequence *> transformed_strips)
bool seq_transform_check_overlap(blender::Span<Sequence *> transformed_strips)
{
for (Sequence *seq : transformed_strips) {
if (seq->flag & SEQ_OVERLAP) {

View File

@ -8,16 +8,20 @@
#include "MEM_guardedalloc.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "BLI_math_matrix.h"
#include "BLI_math_vector.h"
#include "BKE_context.hh"
#include "SEQ_iterator.hh"
#include "SEQ_relations.hh"
#include "SEQ_retiming.hh"
#include "SEQ_sequencer.hh"
#include "SEQ_transform.hh"
#include "transform.hh"
#include "transform_convert.hh"
@ -60,11 +64,34 @@ static TransData *SeqToTransData(const Scene *scene,
return td;
}
static void freeSeqData(TransInfo * /*t*/,
TransDataContainer *tc,
TransCustomData * /*custom_data*/)
static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData * /*custom_data*/)
{
TransData *td = (TransData *)tc->data;
const TransData *const td = (TransData *)tc->data;
Scene *scene = t->scene;
const Editing *ed = SEQ_editing_get(t->scene);
/* Handle overlapping strips. */
blender::VectorSet<Sequence *> transformed_strips;
for (int i = 0; i < tc->data_len; i++) {
Sequence *seq = ((TransDataSeq *)(td + i)->extra)->seq;
transformed_strips.add(seq);
}
ListBase *seqbasep = SEQ_active_seqbase_get(ed);
SEQ_iterator_set_expand(scene, seqbasep, transformed_strips, SEQ_query_strip_effect_chain);
blender::VectorSet<Sequence *> dependant;
dependant.add_multiple(transformed_strips);
dependant.remove_if(
[&](Sequence *seq) { return SEQ_transform_sequence_can_be_translated(seq); });
if (seq_transform_check_overlap(transformed_strips)) {
const bool use_sync_markers = (((SpaceSeq *)t->area->spacedata.first)->flag &
SEQ_MARKER_TRANS) != 0;
SEQ_transform_handle_overlap(scene, seqbasep, transformed_strips, dependant, use_sync_markers);
}
MEM_freeN(td->extra);
}
@ -103,10 +130,14 @@ static void recalcData_sequencer_retiming(TransInfo *t)
const TransData2D *td2d = nullptr;
int i;
blender::VectorSet<Sequence *> transformed_strips;
for (i = 0, td = tc->data, td2d = tc->data_2d; i < tc->data_len; i++, td++, td2d++) {
const TransDataSeq *tdseq = static_cast<TransDataSeq *>(td->extra);
Sequence *seq = tdseq->seq;
transformed_strips.add(seq);
/* Calculate translation. */
const blender::MutableSpan keys = SEQ_retiming_keys_get(seq);
@ -123,6 +154,17 @@ static void recalcData_sequencer_retiming(TransInfo *t)
SEQ_relations_invalidate_cache_preprocessed(t->scene, seq);
}
/* Test overlap, displays red outline. */
Editing *ed = SEQ_editing_get(t->scene);
SEQ_iterator_set_expand(
t->scene, SEQ_active_seqbase_get(ed), transformed_strips, SEQ_query_strip_effect_chain);
for (Sequence *seq : transformed_strips) {
seq->flag &= ~SEQ_OVERLAP;
if (SEQ_transform_test_overlap(t->scene, SEQ_active_seqbase_get(ed), seq)) {
seq->flag |= SEQ_OVERLAP;
}
}
}
TransConvertTypeInfo TransConvertType_SequencerRetiming = {

View File

@ -108,6 +108,7 @@ enum eGPUSeqFlags : uint32_t {
GPU_SEQ_FLAG_SELECTED_RH = (1u << 12u),
GPU_SEQ_FLAG_DRAW_LH = (1u << 13u),
GPU_SEQ_FLAG_DRAW_RH = (1u << 14u),
GPU_SEQ_FLAG_OVERLAP = (1u << 15u),
GPU_SEQ_FLAG_ANY_HANDLE = GPU_SEQ_FLAG_SELECTED_LH | GPU_SEQ_FLAG_SELECTED_RH |
GPU_SEQ_FLAG_DRAW_LH | GPU_SEQ_FLAG_DRAW_RH

View File

@ -193,7 +193,9 @@ void main()
/* Active, but not selected strips get a thin inner line. */
bool active_strip = (strip.flags & GPU_SEQ_FLAG_ACTIVE) != 0;
if (active_strip && !selected) {
/* When moving the retiming keys, the strip might overlap even if it isn't selected. */
bool overlaps = (strip.flags & GPU_SEQ_FLAG_OVERLAP) != 0;
if ((active_strip && !selected) || overlaps) {
col = add_outline(sdf, 1.0, 2.0, col, col_outline);
}