Fix: VSE Slip Strips operator doesn't move effect strips inside of a meta strip. #113200
|
@ -480,74 +480,34 @@ void SEQUENCER_OT_snap(wmOperatorType *ot)
|
|||
* \{ */
|
||||
|
||||
struct SlipData {
|
||||
int init_mouse[2];
|
||||
float init_mouseloc[2];
|
||||
TransSeq *ts;
|
||||
int previous_offset;
|
||||
Sequence **seq_array;
|
||||
bool *trim;
|
||||
int num_seq;
|
||||
bool slow;
|
||||
int slow_offset; /* Offset at the point where offset was turned on. */
|
||||
NumInput num_input;
|
||||
};
|
||||
|
||||
static void transseq_backup(TransSeq *ts, Sequence *seq)
|
||||
static void slip_add_sequences(ListBase *seqbasep, Sequence **seq_array)
|
||||
{
|
||||
ts->content_start = SEQ_time_start_frame_get(seq);
|
||||
ts->start = seq->start;
|
||||
ts->machine = seq->machine;
|
||||
ts->startofs = seq->startofs;
|
||||
ts->endofs = seq->endofs;
|
||||
ts->anim_startofs = seq->anim_startofs;
|
||||
ts->anim_endofs = seq->anim_endofs;
|
||||
ts->len = seq->len;
|
||||
}
|
||||
|
||||
static void transseq_restore(TransSeq *ts, Sequence *seq)
|
||||
{
|
||||
seq->start = ts->start;
|
||||
seq->machine = ts->machine;
|
||||
seq->startofs = ts->startofs;
|
||||
seq->endofs = ts->endofs;
|
||||
seq->anim_startofs = ts->anim_startofs;
|
||||
seq->anim_endofs = ts->anim_endofs;
|
||||
seq->len = ts->len;
|
||||
}
|
||||
|
||||
static int slip_add_sequences_recursive(
|
||||
ListBase *seqbasep, Sequence **seq_array, bool *trim, int offset, bool do_trim)
|
||||
{
|
||||
int num_items = 0;
|
||||
int i = 0;
|
||||
|
||||
LISTBASE_FOREACH (Sequence *, seq, seqbasep) {
|
||||
if (!do_trim || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
|
||||
seq_array[offset + num_items] = seq;
|
||||
trim[offset + num_items] = do_trim && ((seq->type & SEQ_TYPE_EFFECT) == 0);
|
||||
num_items++;
|
||||
|
||||
if (seq->type == SEQ_TYPE_META) {
|
||||
/* Trim the sub-sequences. */
|
||||
num_items += slip_add_sequences_recursive(
|
||||
&seq->seqbase, seq_array, trim, num_items + offset, false);
|
||||
}
|
||||
if (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT)) {
|
||||
seq_array[i] = seq;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return num_items;
|
||||
}
|
||||
|
||||
static int slip_count_sequences_recursive(ListBase *seqbasep, bool first_level)
|
||||
static int slip_count_sequences(ListBase *seqbasep)
|
||||
{
|
||||
int trimmed_sequences = 0;
|
||||
|
||||
LISTBASE_FOREACH (Sequence *, seq, seqbasep) {
|
||||
if (!first_level || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
|
||||
if (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT)) {
|
||||
trimmed_sequences++;
|
||||
|
||||
if (seq->type == SEQ_TYPE_META) {
|
||||
/* Trim the sub-sequences. */
|
||||
trimmed_sequences += slip_count_sequences_recursive(&seq->seqbase, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -563,8 +523,8 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
|
|||
int num_seq;
|
||||
View2D *v2d = UI_view2d_fromcontext(C);
|
||||
|
||||
/* Recursively count the trimmed elements. */
|
||||
num_seq = slip_count_sequences_recursive(ed->seqbasep, true);
|
||||
/* Count the amount of elements to trim. */
|
||||
num_seq = slip_count_sequences(ed->seqbasep);
|
||||
|
||||
if (num_seq == 0) {
|
||||
return OPERATOR_CANCELLED;
|
||||
|
@ -572,10 +532,9 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
|
|||
|
||||
data = MEM_cnew<SlipData>("trimdata");
|
||||
op->customdata = static_cast<void *>(data);
|
||||
data->ts = MEM_cnew_array<TransSeq>(num_seq, "trimdata_transform");
|
||||
data->seq_array = MEM_cnew_array<Sequence *>(num_seq, "trimdata_sequences");
|
||||
data->trim = MEM_cnew_array<bool>(num_seq, "trimdata_trim");
|
||||
data->num_seq = num_seq;
|
||||
data->previous_offset = 0;
|
||||
|
||||
initNumInput(&data->num_input);
|
||||
data->num_input.idx_max = 0;
|
||||
|
@ -583,15 +542,10 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
|
|||
data->num_input.unit_sys = USER_UNIT_NONE;
|
||||
data->num_input.unit_type[0] = 0;
|
||||
|
||||
slip_add_sequences_recursive(ed->seqbasep, data->seq_array, data->trim, 0, true);
|
||||
|
||||
for (int i = 0; i < num_seq; i++) {
|
||||
transseq_backup(data->ts + i, data->seq_array[i]);
|
||||
}
|
||||
slip_add_sequences(ed->seqbasep, data->seq_array);
|
||||
|
||||
UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
|
||||
|
||||
copy_v2_v2_int(data->init_mouse, event->mval);
|
||||
copy_v2_v2(data->init_mouseloc, mouseloc);
|
||||
|
||||
data->slow = false;
|
||||
|
@ -604,7 +558,7 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
|
|||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static void sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
|
||||
static void sequencer_slip_strips(Scene *scene, SlipData *data, int delta)
|
||||
|
||||
{
|
||||
for (int i = data->num_seq - 1; i >= 0; i--) {
|
||||
Sequence *seq = data->seq_array[i];
|
||||
|
@ -614,11 +568,7 @@ static void sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
|
|||
continue;
|
||||
}
|
||||
|
||||
seq->start = data->ts[i].start + offset;
|
||||
if (data->trim[i]) {
|
||||
seq->startofs = data->ts[i].startofs - offset;
|
||||
seq->endofs = data->ts[i].endofs + offset;
|
||||
}
|
||||
SEQ_time_slip_strip(scene, seq, delta);
|
||||
}
|
||||
|
||||
for (int i = data->num_seq - 1; i >= 0; i--) {
|
||||
|
@ -627,26 +577,31 @@ static void sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
|
|||
}
|
||||
}
|
||||
|
||||
/* Make sure, that each strip contains at least 1 frame of content. */
|
||||
static void sequencer_slip_apply_limits(const Scene *scene, SlipData *data, int *offset)
|
||||
/* Make sure, that each strip contains at least 1 frame of content.
|
||||
* Returns clamped offset relative to current strip positions. */
|
||||
static int sequencer_slip_apply_limits(const Scene *scene, SlipData *data, int *offset)
|
||||
{
|
||||
int delta_offset = *offset - data->previous_offset;
|
||||
|
||||
for (int i = 0; i < data->num_seq; i++) {
|
||||
if (data->trim[i]) {
|
||||
Sequence *seq = data->seq_array[i];
|
||||
int seq_content_start = data->ts[i].start + *offset;
|
||||
int seq_content_end = seq_content_start + seq->len + seq->anim_startofs + seq->anim_endofs;
|
||||
int diff = 0;
|
||||
Sequence *seq = data->seq_array[i];
|
||||
int seq_content_start = SEQ_time_start_frame_get(seq) + delta_offset;
|
||||
int seq_content_end = seq_content_start + seq->len + seq->anim_startofs + seq->anim_endofs;
|
||||
int diff = 0;
|
||||
|
||||
if (seq_content_start >= SEQ_time_right_handle_frame_get(scene, seq)) {
|
||||
diff = SEQ_time_right_handle_frame_get(scene, seq) - seq_content_start - 1;
|
||||
}
|
||||
|
||||
if (seq_content_end <= SEQ_time_left_handle_frame_get(scene, seq)) {
|
||||
diff = SEQ_time_left_handle_frame_get(scene, seq) - seq_content_end + 1;
|
||||
}
|
||||
*offset += diff;
|
||||
if (seq_content_start >= SEQ_time_right_handle_frame_get(scene, seq)) {
|
||||
diff = SEQ_time_right_handle_frame_get(scene, seq) - seq_content_start - 1;
|
||||
}
|
||||
|
||||
if (seq_content_end <= SEQ_time_left_handle_frame_get(scene, seq)) {
|
||||
diff = SEQ_time_left_handle_frame_get(scene, seq) - seq_content_end + 1;
|
||||
}
|
||||
*offset += diff;
|
||||
delta_offset += diff;
|
||||
}
|
||||
data->previous_offset = *offset;
|
||||
|
||||
return delta_offset;
|
||||
}
|
||||
|
||||
static int sequencer_slip_exec(bContext *C, wmOperator *op)
|
||||
|
@ -655,8 +610,8 @@ static int sequencer_slip_exec(bContext *C, wmOperator *op)
|
|||
Editing *ed = SEQ_editing_get(scene);
|
||||
int offset = RNA_int_get(op->ptr, "offset");
|
||||
|
||||
/* Recursively count the trimmed elements. */
|
||||
int num_seq = slip_count_sequences_recursive(ed->seqbasep, true);
|
||||
/* Count the amount of elements to trim. */
|
||||
int num_seq = slip_count_sequences(ed->seqbasep);
|
||||
|
||||
if (num_seq == 0) {
|
||||
return OPERATOR_CANCELLED;
|
||||
|
@ -664,23 +619,15 @@ static int sequencer_slip_exec(bContext *C, wmOperator *op)
|
|||
|
||||
SlipData *data = MEM_cnew<SlipData>("trimdata");
|
||||
op->customdata = static_cast<void *>(data);
|
||||
data->ts = MEM_cnew_array<TransSeq>(num_seq, "trimdata_transform");
|
||||
data->seq_array = MEM_cnew_array<Sequence *>(num_seq, "trimdata_sequences");
|
||||
data->trim = MEM_cnew_array<bool>(num_seq, "trimdata_trim");
|
||||
data->num_seq = num_seq;
|
||||
|
||||
slip_add_sequences_recursive(ed->seqbasep, data->seq_array, data->trim, 0, true);
|
||||
|
||||
for (int i = 0; i < num_seq; i++) {
|
||||
transseq_backup(data->ts + i, data->seq_array[i]);
|
||||
}
|
||||
slip_add_sequences(ed->seqbasep, data->seq_array);
|
||||
|
||||
sequencer_slip_apply_limits(scene, data, &offset);
|
||||
sequencer_slip_recursively(scene, data, offset);
|
||||
sequencer_slip_strips(scene, data, offset);
|
||||
|
||||
MEM_freeN(data->seq_array);
|
||||
MEM_freeN(data->trim);
|
||||
MEM_freeN(data->ts);
|
||||
MEM_freeN(data);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
|
@ -708,7 +655,6 @@ static void sequencer_slip_update_header(Scene *scene, ScrArea *area, SlipData *
|
|||
|
||||
static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
SlipData *data = (SlipData *)op->customdata;
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
|
@ -721,12 +667,13 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
|
|||
applyNumInput(&data->num_input, &offset_fl);
|
||||
int offset = round_fl_to_int(offset_fl);
|
||||
|
||||
sequencer_slip_apply_limits(scene, data, &offset);
|
||||
const int delta_offset = sequencer_slip_apply_limits(scene, data, &offset);
|
||||
sequencer_slip_update_header(scene, area, data, offset);
|
||||
|
||||
RNA_int_set(op->ptr, "offset", offset);
|
||||
|
||||
sequencer_slip_recursively(scene, data, offset);
|
||||
sequencer_slip_strips(scene, data, delta_offset);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
|
@ -753,12 +700,13 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
|
|||
UI_view2d_region_to_view(v2d, mouse_x, 0, &mouseloc[0], &mouseloc[1]);
|
||||
offset = mouseloc[0] - data->init_mouseloc[0];
|
||||
|
||||
sequencer_slip_apply_limits(scene, data, &offset);
|
||||
const int delta_offset = sequencer_slip_apply_limits(scene, data, &offset);
|
||||
sequencer_slip_update_header(scene, area, data, offset);
|
||||
|
||||
RNA_int_set(op->ptr, "offset", offset);
|
||||
|
||||
sequencer_slip_recursively(scene, data, offset);
|
||||
sequencer_slip_strips(scene, data, delta_offset);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
}
|
||||
break;
|
||||
|
@ -768,8 +716,6 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
|
|||
case EVT_RETKEY:
|
||||
case EVT_SPACEKEY: {
|
||||
MEM_freeN(data->seq_array);
|
||||
MEM_freeN(data->trim);
|
||||
MEM_freeN(data->ts);
|
||||
MEM_freeN(data);
|
||||
op->customdata = nullptr;
|
||||
if (area) {
|
||||
|
@ -782,18 +728,10 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
|
|||
|
||||
case EVT_ESCKEY:
|
||||
case RIGHTMOUSE: {
|
||||
for (int i = 0; i < data->num_seq; i++) {
|
||||
transseq_restore(data->ts + i, data->seq_array[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < data->num_seq; i++) {
|
||||
Sequence *seq = data->seq_array[i];
|
||||
SEQ_add_reload_new_file(bmain, scene, seq, false);
|
||||
}
|
||||
int offset = RNA_int_get(op->ptr, "offset");
|
||||
sequencer_slip_strips(scene, data, -offset);
|
||||
|
||||
MEM_freeN(data->seq_array);
|
||||
MEM_freeN(data->ts);
|
||||
MEM_freeN(data->trim);
|
||||
MEM_freeN(data);
|
||||
op->customdata = nullptr;
|
||||
|
||||
|
@ -830,12 +768,13 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
|
|||
applyNumInput(&data->num_input, &offset_fl);
|
||||
int offset = round_fl_to_int(offset_fl);
|
||||
|
||||
sequencer_slip_apply_limits(scene, data, &offset);
|
||||
const int delta_offset = sequencer_slip_apply_limits(scene, data, &offset);
|
||||
sequencer_slip_update_header(scene, area, data, offset);
|
||||
|
||||
RNA_int_set(op->ptr, "offset", offset);
|
||||
|
||||
sequencer_slip_recursively(scene, data, offset);
|
||||
sequencer_slip_strips(scene, data, delta_offset);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
}
|
||||
|
||||
|
|
|
@ -120,7 +120,10 @@ void SEQ_time_start_frame_set(const Scene *scene, Sequence *seq, int timeline_fr
|
|||
* \note this function is currently only used internally and in versioning code.
|
||||
*/
|
||||
void SEQ_time_update_meta_strip_range(const Scene *scene, Sequence *seq_meta);
|
||||
|
||||
/**
|
||||
* Move contents of a strip without moving the strip handles.
|
||||
*/
|
||||
void SEQ_time_slip_strip(const Scene *scene, Sequence *seq, int delta);
|
||||
/**
|
||||
* Get difference between scene and movie strip frame-rate.
|
||||
*/
|
||||
|
|
|
@ -576,3 +576,51 @@ void seq_time_translate_handles(const Scene *scene, Sequence *seq, const int off
|
|||
seq_time_update_effects_strip_range(scene, effects);
|
||||
SEQ_time_update_meta_strip_range(scene, seq_sequence_lookup_meta_by_seq(scene, seq));
|
||||
}
|
||||
|
||||
static void seq_time_slip_strip_ex(const Scene *scene, Sequence *seq, int delta, bool recursed)
|
||||
{
|
||||
if (delta == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Skip effect strips where the length is dependent on another strip,
|
||||
* as they are calculated with #seq_time_update_effects_strip_range. */
|
||||
if (seq->seq1 != nullptr || seq->seq2 != nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Effects only have a start frame and a length, so unless we're inside
|
||||
* a meta strip, there's no need to do anything. */
|
||||
if (!recursed && (seq->type & SEQ_TYPE_EFFECT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Move strips inside meta strip. */
|
||||
if (seq->type == SEQ_TYPE_META) {
|
||||
/* If the meta strip has no contents, don't do anything. */
|
||||
if (BLI_listbase_is_empty(&seq->seqbase)) {
|
||||
return;
|
||||
}
|
||||
LISTBASE_FOREACH (Sequence *, seq_child, &seq->seqbase) {
|
||||
seq_time_slip_strip_ex(scene, seq_child, delta, true);
|
||||
ok_what marked this conversation as resolved
Richard Antalik
commented
Please use Please use `LISTBASE_FOREACH` macro
|
||||
}
|
||||
}
|
||||
|
||||
seq->start = seq->start + delta;
|
||||
if (!recursed) {
|
||||
seq->startofs = seq->startofs - delta;
|
||||
seq->endofs = seq->endofs + delta;
|
||||
}
|
||||
|
||||
/* Only to make files usable in older versions. */
|
||||
seq->startdisp = SEQ_time_left_handle_frame_get(scene, seq);
|
||||
seq->enddisp = SEQ_time_right_handle_frame_get(scene, seq);
|
||||
|
||||
blender::Span effects = seq_sequence_lookup_effects_by_seq(scene, seq);
|
||||
seq_time_update_effects_strip_range(scene, effects);
|
||||
}
|
||||
|
||||
void SEQ_time_slip_strip(const Scene *scene, Sequence *seq, int delta)
|
||||
{
|
||||
seq_time_slip_strip_ex(scene, seq, delta, false);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
I guess this function is not recursive anymore?