VSE: Refactor delete operator and API

Operator logic is limited to iterating over selection and executing
same code as python API does.

Functional changes:

 - No attempt to preserve effects is made. Dependant effects are deleted.
 - No attempt to change meta strip boundaries.

Partially fixes T73828

Reviewed By: campbellbarton

Differential Revision: https://developer.blender.org/D6892
This commit is contained in:
Richard Antalik 2020-07-26 16:07:34 +02:00
parent f0e370a650
commit 076d033e10
Notes: blender-bot 2023-02-14 08:39:23 +01:00
Referenced by issue #73828, VSE: using python to remove a scene strip with effect applied causes... weirdness
4 changed files with 70 additions and 118 deletions

View File

@ -625,6 +625,10 @@ void BKE_sequencer_color_balance_apply(struct StripColorBalance *cb,
void BKE_sequencer_all_free_anim_ibufs(struct Scene *scene, int cfra);
bool BKE_sequencer_check_scene_recursion(struct Scene *scene, struct ReportList *reports);
bool BKE_sequencer_render_loop_check(struct Sequence *seq_main, struct Sequence *seq);
void BKE_sequencer_flag_for_removal(struct Scene *scene,
struct ListBase *seqbase,
struct Sequence *seq);
void BKE_sequencer_remove_flagged_sequences(struct Scene *scene, struct ListBase *seqbase);
#ifdef __cplusplus
}

View File

@ -6069,3 +6069,61 @@ bool BKE_sequencer_render_loop_check(Sequence *seq_main, Sequence *seq)
return false;
}
static void sequencer_flag_users_for_removal(Scene *scene, ListBase *seqbase, Sequence *seq)
{
LISTBASE_FOREACH (Sequence *, user_seq, seqbase) {
/* Look in metas for usage of seq. */
if (user_seq->type == SEQ_TYPE_META) {
sequencer_flag_users_for_removal(scene, &user_seq->seqbase, seq);
}
/* Clear seq from modifiers. */
SequenceModifierData *smd;
for (smd = user_seq->modifiers.first; smd; smd = smd->next) {
if (smd->mask_sequence == seq) {
smd->mask_sequence = NULL;
}
}
/* Remove effects, that use seq. */
if ((user_seq->seq1 && user_seq->seq1 == seq) || (user_seq->seq2 && user_seq->seq2 == seq) ||
(user_seq->seq3 && user_seq->seq3 == seq)) {
user_seq->flag |= SEQ_FLAG_DELETE;
/* Strips can be used as mask even if not in same seqbase. */
sequencer_flag_users_for_removal(scene, &scene->ed->seqbase, user_seq);
}
}
}
/* Flag seq and its users (effects) for removal. */
void BKE_sequencer_flag_for_removal(Scene *scene, ListBase *seqbase, Sequence *seq)
{
if (seq == NULL || (seq->flag & SEQ_FLAG_DELETE) != 0) {
return;
}
/* Flag and remove meta children. */
if (seq->type == SEQ_TYPE_META) {
LISTBASE_FOREACH (Sequence *, meta_child, &seq->seqbase) {
BKE_sequencer_flag_for_removal(scene, &seq->seqbase, meta_child);
}
}
seq->flag |= SEQ_FLAG_DELETE;
sequencer_flag_users_for_removal(scene, seqbase, seq);
}
/* Remove all flagged sequences, return true if sequence is removed. */
void BKE_sequencer_remove_flagged_sequences(Scene *scene, ListBase *seqbase)
{
LISTBASE_FOREACH_MUTABLE (Sequence *, seq, seqbase) {
if (seq->flag & SEQ_FLAG_DELETE) {
if (seq->type == SEQ_TYPE_META) {
BKE_sequencer_remove_flagged_sequences(scene, &seq->seqbase);
}
BLI_remlink(seqbase, seq);
BKE_sequence_free(scene, seq, true);
}
}
}

View File

@ -666,74 +666,6 @@ int seq_effect_find_selected(Scene *scene,
/** \name Delete Utilities
* \{ */
static Sequence *del_seq_find_replace_recurs(Scene *scene, Sequence *seq)
{
Sequence *seq1, *seq2, *seq3;
/* Try to find a replacement input sequence, and flag for later deletion if
* no replacement can be found. */
if (!seq) {
return NULL;
}
if (!(seq->type & SEQ_TYPE_EFFECT)) {
return ((seq->flag & SELECT) ? NULL : seq);
}
if (!(seq->flag & SELECT)) {
/* Try to find replacement for effect inputs. */
seq1 = del_seq_find_replace_recurs(scene, seq->seq1);
seq2 = del_seq_find_replace_recurs(scene, seq->seq2);
seq3 = del_seq_find_replace_recurs(scene, seq->seq3);
if (seq1 == seq->seq1 && seq2 == seq->seq2 && seq3 == seq->seq3) {
/* Pass. */
}
else if (seq1 || seq2 || seq3) {
seq->seq1 = (seq1) ? seq1 : (seq2) ? seq2 : seq3;
seq->seq2 = (seq2) ? seq2 : (seq1) ? seq1 : seq3;
seq->seq3 = (seq3) ? seq3 : (seq1) ? seq1 : seq2;
BKE_sequencer_update_changed_seq_and_deps(scene, seq, 1, 1);
}
else {
seq->flag |= SELECT; /* Mark for delete. */
}
}
if (seq->flag & SELECT) {
if ((seq1 = del_seq_find_replace_recurs(scene, seq->seq1))) {
return seq1;
}
if ((seq2 = del_seq_find_replace_recurs(scene, seq->seq2))) {
return seq2;
}
if ((seq3 = del_seq_find_replace_recurs(scene, seq->seq3))) {
return seq3;
}
return NULL;
}
return seq;
}
static void del_seq_clear_modifiers_recurs(Scene *scene, Sequence *deleting_sequence)
{
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *current_sequence;
SEQP_BEGIN (ed, current_sequence) {
if (!(current_sequence->flag & SELECT) && current_sequence != deleting_sequence) {
SequenceModifierData *smd;
for (smd = current_sequence->modifiers.first; smd; smd = smd->next) {
if (smd->mask_sequence == deleting_sequence) {
smd->mask_sequence = NULL;
}
}
}
}
SEQ_END;
}
static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short deleteall)
{
Sequence *seq, *seqn;
@ -2582,61 +2514,18 @@ static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq;
MetaStack *ms;
bool nothing_selected = true;
BKE_sequencer_prefetch_stop(scene);
seq = BKE_sequencer_active_get(scene);
if (seq && seq->flag & SELECT) { /* Avoid a loop since this is likely to be selected. */
nothing_selected = false;
}
else {
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if (seq->flag & SELECT) {
nothing_selected = false;
break;
}
SEQP_BEGIN (scene->ed, seq) {
if (seq->flag & SELECT) {
BKE_sequencer_flag_for_removal(scene, ed->seqbasep, seq);
}
}
if (nothing_selected) {
return OPERATOR_FINISHED;
}
/* For effects and modifiers, try to find a replacement input. */
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if (!(seq->flag & SELECT)) {
if ((seq->type & SEQ_TYPE_EFFECT)) {
del_seq_find_replace_recurs(scene, seq);
}
}
else {
del_seq_clear_modifiers_recurs(scene, seq);
}
}
/* Delete all selected strips. */
recurs_del_seq_flag(scene, ed->seqbasep, SELECT, 0);
/* Update lengths, etc. */
seq = ed->seqbasep->first;
while (seq) {
BKE_sequence_calc(scene, seq);
seq = seq->next;
}
/* Free parent metas. */
ms = ed->metastack.last;
while (ms) {
BKE_sequence_calc(scene, ms->parseq);
ms = ms->prev;
}
SEQ_END;
BKE_sequencer_remove_flagged_sequences(scene, ed->seqbasep);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
}

View File

@ -370,13 +370,14 @@ static void rna_Sequences_remove(
Sequence *seq = seq_ptr->data;
Scene *scene = (Scene *)id;
if (BLI_remlink_safe(&ed->seqbase, seq) == false) {
if (BLI_findindex(&ed->seqbase, seq) == -1) {
BKE_reportf(
reports, RPT_ERROR, "Sequence '%s' not in scene '%s'", seq->name + 2, scene->id.name + 2);
return;
}
BKE_sequence_free(scene, seq, true);
BKE_sequencer_flag_for_removal(scene, &ed->seqbase, seq);
BKE_sequencer_remove_flagged_sequences(scene, &ed->seqbase);
RNA_POINTER_INVALIDATE(seq_ptr);
DEG_relations_tag_update(bmain);