Cleanup: Minimize seq->tmp usage

Using this persistent field in `select_more_less_seq__internal` was
inapropriate in this case.

Split select more/less and linked code, because it was mixed in
`select_more_less_seq__internal()`
These operators work in completely different way.
`select_linked_internal()` doesn't use seq->tmp at all.

`seq->tmp` was used to mask strips selected by operator while iterating.
Use GSet to store temporary data instead of `seq->tmp`.

Reviewed By: sergey

Differential Revision: https://developer.blender.org/D10326
This commit is contained in:
Richard Antalik 2021-02-05 16:17:14 +01:00
parent 16abe9343a
commit 66923031e6
Notes: blender-bot 2023-02-13 18:34:10 +01:00
Referenced by commit adafd7257d, Fix T88635: VSE: Select Linked gives unpredictable results
Referenced by issue #88635, Video Sequencer: Select Linked gives unpredictable results
1 changed files with 69 additions and 54 deletions

View File

@ -26,6 +26,7 @@
#include <string.h>
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@ -771,69 +772,83 @@ void SEQUENCER_OT_select(wmOperatorType *ot)
* \{ */
/* Run recursively to select linked. */
static bool select_more_less_seq__internal(Scene *scene, bool sel, const bool linked)
static bool select_linked_internal(Scene *scene)
{
Editing *ed = SEQ_editing_get(scene, false);
Sequence *seq, *neighbor;
bool changed = false;
int isel;
if (ed == NULL) {
return changed;
return false;
}
if (sel) {
sel = SELECT;
isel = 0;
}
else {
sel = 0;
isel = SELECT;
}
bool changed = false;
if (!linked) {
/* If not linked we only want to touch each seq once, newseq. */
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
seq->tmp = NULL;
LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
if ((seq->flag & SELECT) != 0) {
continue;
}
/* Only get unselected neighbors. */
Sequence *neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_LEFT, 0);
if (neighbor) {
neighbor->flag |= SELECT;
recurs_sel_seq(neighbor);
changed = true;
}
neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, 0);
if (neighbor) {
neighbor->flag |= SELECT;
recurs_sel_seq(neighbor);
changed = true;
}
}
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if ((seq->flag & SELECT) == sel) {
if (linked || (seq->tmp == NULL)) {
/* Only get unselected neighbors. */
neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_LEFT, isel);
if (neighbor) {
if (sel) {
neighbor->flag |= SELECT;
recurs_sel_seq(neighbor);
}
else {
neighbor->flag &= ~SELECT;
}
if (!linked) {
neighbor->tmp = (Sequence *)1;
}
changed = true;
}
neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, isel);
if (neighbor) {
if (sel) {
neighbor->flag |= SELECT;
recurs_sel_seq(neighbor);
}
else {
neighbor->flag &= ~SELECT;
}
if (!linked) {
neighbor->tmp = (Sequence *)1;
}
changed = true;
}
}
return changed;
}
/* Select only one linked strip on each side. */
static bool select_more_less_seq__internal(Scene *scene, bool select_more)
{
Editing *ed = SEQ_editing_get(scene, false);
if (ed == NULL) {
return false;
}
GSet *neighbors = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "Linked strips");
const int neighbor_selection_filter = select_more ? 0 : SELECT;
const int selection_filter = select_more ? SELECT : 0;
LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
if ((seq->flag & SELECT) != selection_filter) {
continue;
}
Sequence *neighbor = find_neighboring_sequence(
scene, seq, SEQ_SIDE_LEFT, neighbor_selection_filter);
if (neighbor) {
BLI_gset_add(neighbors, neighbor);
}
neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, neighbor_selection_filter);
if (neighbor) {
BLI_gset_add(neighbors, neighbor);
}
}
bool changed = false;
GSetIterator gsi;
BLI_gsetIterator_init(&gsi, neighbors);
while (!BLI_gsetIterator_done(&gsi)) {
Sequence *neighbor = BLI_gsetIterator_getKey(&gsi);
if (select_more) {
neighbor->flag |= SELECT;
recurs_sel_seq(neighbor);
}
else {
neighbor->flag &= ~SELECT;
}
changed = true;
BLI_gsetIterator_step(&gsi);
}
BLI_gset_free(neighbors, NULL);
return changed;
}
@ -841,7 +856,7 @@ static int sequencer_select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
if (!select_more_less_seq__internal(scene, true, false)) {
if (!select_more_less_seq__internal(scene, true)) {
return OPERATOR_CANCELLED;
}
@ -877,7 +892,7 @@ static int sequencer_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
if (!select_more_less_seq__internal(scene, false, false)) {
if (!select_more_less_seq__internal(scene, false)) {
return OPERATOR_CANCELLED;
}
@ -934,7 +949,7 @@ static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, cons
selected = 1;
while (selected) {
selected = select_more_less_seq__internal(scene, 1, 1);
selected = select_linked_internal(scene);
}
ED_outliner_select_sync_from_sequence_tag(C);
@ -975,7 +990,7 @@ static int sequencer_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
selected = true;
while (selected) {
selected = select_more_less_seq__internal(scene, true, true);
selected = select_linked_internal(scene);
}
ED_outliner_select_sync_from_sequence_tag(C);