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:
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
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue