From 6b35d9e6fbef49d4ce61604c27393425c16cd7a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix?= Date: Mon, 27 Jun 2022 19:29:41 +0200 Subject: VSE: Add API function to select displayed meta strip Use function `sequence_editor.display_stack(meta_strip)` to set displayed timeline content. To view top-level timeline, that does not belong to any meta strip, pass `None` as argument. Differential Revision: https://developer.blender.org/D12048 --- .../editors/space_sequencer/sequencer_edit.c | 16 +++---- source/blender/makesrna/intern/rna_sequencer.c | 32 +++++++++++++ source/blender/sequencer/SEQ_relations.h | 1 + source/blender/sequencer/SEQ_sequencer.h | 19 ++++---- source/blender/sequencer/intern/sequencer.c | 55 ++++++++++++++++++---- source/blender/sequencer/intern/strip_edit.c | 17 +------ source/blender/sequencer/intern/strip_relations.c | 13 +++++ 7 files changed, 107 insertions(+), 46 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 16f663110ec..76dd43586d1 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -1911,11 +1911,9 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op)) SEQ_prefetch_stop(scene); if (active_seq && active_seq->type == SEQ_TYPE_META && active_seq->flag & SELECT) { - /* Enter meta-strip. */ - SEQ_meta_stack_alloc(ed, active_seq); - SEQ_seqbase_active_set(ed, &active_seq->seqbase); - SEQ_channels_displayed_set(ed, &active_seq->channels); + /* Deselect active meta seq. */ SEQ_select_active_set(scene, NULL); + SEQ_meta_stack_set(scene, active_seq); } else { /* Exit meta-strip if possible. */ @@ -1923,14 +1921,12 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } - MetaStack *ms = SEQ_meta_stack_active_get(ed); - SEQ_seqbase_active_set(ed, ms->oldbasep); - SEQ_channels_displayed_set(ed, ms->old_channels); - SEQ_select_active_set(scene, ms->parseq); - SEQ_meta_stack_free(ed, ms); + /* Display parent meta. */ + Sequence *meta_parent = SEQ_meta_stack_pop(ed); + SEQ_select_active_set(scene, meta_parent); } - DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); + // DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 100d90df5d6..9bfdcda79a7 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -43,6 +43,7 @@ #include "SEQ_prefetch.h" #include "SEQ_proxy.h" #include "SEQ_relations.h" +#include "SEQ_select.h" #include "SEQ_sequencer.h" #include "SEQ_sound.h" #include "SEQ_time.h" @@ -1107,6 +1108,26 @@ static void rna_SequenceEditor_overlay_frame_set(PointerRNA *ptr, int value) } } +static void rna_SequenceEditor_display_stack(ID *id, + Editing *ed, + ReportList *reports, + Sequence *seqm) +{ + /* Check for non-meta sequence */ + if (seqm != NULL && seqm->type != SEQ_TYPE_META && SEQ_exists_in_seqbase(seqm, &ed->seqbase)) { + BKE_report(reports, RPT_ERROR, "Sequence type must be 'META'"); + return; + } + + /* Get editing base of meta sequence */ + Scene *scene = (Scene *)id; + SEQ_meta_stack_set(scene, seqm); + /* De-activate strip. This is to prevent strip from different timeline being drawn. */ + SEQ_select_active_set(scene, NULL); + + WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene); +} + static bool modifier_seq_cmp_fn(Sequence *seq, void *arg_pt) { SequenceSearchData *data = arg_pt; @@ -2116,6 +2137,8 @@ static void rna_def_channel(BlenderRNA *brna) static void rna_def_editor(BlenderRNA *brna) { StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; PropertyRNA *prop; static const EnumPropertyItem editing_storage_items[] = { @@ -2259,6 +2282,15 @@ static void rna_def_editor(BlenderRNA *brna) "Prefetch Frames", "Render frames ahead of current frame in the background for faster playback"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL); + + /* functions */ + + func = RNA_def_function(srna, "display_stack", "rna_SequenceEditor_display_stack"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS); + RNA_def_function_ui_description(func, "Display sequences stack"); + parm = RNA_def_pointer( + func, "meta_sequence", "Sequence", "Meta Sequence", "Meta to display its stack"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); } static void rna_def_filter_video(StructRNA *srna) diff --git a/source/blender/sequencer/SEQ_relations.h b/source/blender/sequencer/SEQ_relations.h index 917f549f16d..9678ac1cc1c 100644 --- a/source/blender/sequencer/SEQ_relations.h +++ b/source/blender/sequencer/SEQ_relations.h @@ -68,6 +68,7 @@ void SEQ_cache_iterate( struct Sequence *SEQ_find_metastrip_by_sequence(ListBase *seqbase /* = ed->seqbase */, struct Sequence *meta /* = NULL */, struct Sequence *seq); +bool SEQ_exists_in_seqbase(const struct Sequence *seq, const struct ListBase *seqbase); #ifdef __cplusplus } diff --git a/source/blender/sequencer/SEQ_sequencer.h b/source/blender/sequencer/SEQ_sequencer.h index 70cba58007f..a77ca1c7baf 100644 --- a/source/blender/sequencer/SEQ_sequencer.h +++ b/source/blender/sequencer/SEQ_sequencer.h @@ -70,27 +70,24 @@ void SEQ_seqbase_active_set(struct Editing *ed, struct ListBase *seqbase); struct Sequence *SEQ_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int type); void SEQ_sequence_free(struct Scene *scene, struct Sequence *seq); /** - * Create and initialize #MetaStack, append it to `ed->metastack` ListBase + * Get #MetaStack that corresponds to current level that is being viewed * - * \param ed: sequence editor data - * \param seq_meta: meta strip - * \return pointer to created meta stack + * \return pointer to meta stack */ -struct MetaStack *SEQ_meta_stack_alloc(struct Editing *ed, struct Sequence *seq_meta); +struct MetaStack *SEQ_meta_stack_active_get(const struct Editing *ed); /** - * Get #MetaStack that corresponds to current level that is being viewed + * Open Meta strip content for editing. * * \param ed: sequence editor data - * \return pointer to meta stack + * \param seqm: meta sequence or NULL for top level view */ -struct MetaStack *SEQ_meta_stack_active_get(const struct Editing *ed); +void SEQ_meta_stack_set(const struct Scene *scene, struct Sequence *dst_seq); /** - * Free #MetaStack and remove it from `ed->metastack` ListBase. + * Close last Meta strip open for editing. * * \param ed: sequence editor data - * \param ms: meta stack */ -void SEQ_meta_stack_free(struct Editing *ed, struct MetaStack *ms); +struct Sequence *SEQ_meta_stack_pop(struct Editing *ed); struct Sequence *SEQ_sequence_dupli_recursive(const struct Scene *scene_src, struct Scene *scene_dst, struct ListBase *new_seq_list, diff --git a/source/blender/sequencer/intern/sequencer.c b/source/blender/sequencer/intern/sequencer.c index ad57412034a..71f4aef6916 100644 --- a/source/blender/sequencer/intern/sequencer.c +++ b/source/blender/sequencer/intern/sequencer.c @@ -397,23 +397,23 @@ void SEQ_seqbase_active_set(Editing *ed, ListBase *seqbase) ed->seqbasep = seqbase; } -MetaStack *SEQ_meta_stack_alloc(Editing *ed, Sequence *seq_meta) +static MetaStack *seq_meta_stack_alloc(const Scene *scene, Sequence *seq_meta) { + Editing *ed = SEQ_editing_get(scene); + MetaStack *ms = MEM_mallocN(sizeof(MetaStack), "metastack"); - BLI_addtail(&ed->metastack, ms); + BLI_addhead(&ed->metastack, ms); ms->parseq = seq_meta; - ms->oldbasep = ed->seqbasep; - ms->old_channels = ed->displayed_channels; + + /* Reference to previously displayed timeline data. */ + Sequence *higher_level_meta = seq_sequence_lookup_meta_by_seq(scene, seq_meta); + ms->oldbasep = higher_level_meta ? &higher_level_meta->seqbase : &ed->seqbase; + ms->old_channels = higher_level_meta ? &higher_level_meta->channels : &ed->channels; + copy_v2_v2_int(ms->disp_range, &ms->parseq->startdisp); return ms; } -void SEQ_meta_stack_free(Editing *ed, MetaStack *ms) -{ - BLI_remlink(&ed->metastack, ms); - MEM_freeN(ms); -} - MetaStack *SEQ_meta_stack_active_get(const Editing *ed) { if (ed == NULL) { @@ -423,6 +423,41 @@ MetaStack *SEQ_meta_stack_active_get(const Editing *ed) return ed->metastack.last; } +void SEQ_meta_stack_set(const Scene *scene, Sequence *seqm) +{ + Editing *ed = SEQ_editing_get(scene); + /* Clear metastack */ + BLI_freelistN(&ed->metastack); + + if (seqm != NULL) { + /* Allocate meta stack in a way, that represents meta hierarchy in timeline. */ + seq_meta_stack_alloc(scene, seqm); + Sequence *meta_parent = seqm; + while (meta_parent = seq_sequence_lookup_meta_by_seq(scene, meta_parent)) { + seq_meta_stack_alloc(scene, meta_parent); + } + + SEQ_seqbase_active_set(ed, &seqm->seqbase); + SEQ_channels_displayed_set(ed, &seqm->channels); + } + else { + /* Go to top level, exiting meta strip. */ + SEQ_seqbase_active_set(ed, &ed->seqbase); + SEQ_channels_displayed_set(ed, &ed->channels); + } +} + +Sequence *SEQ_meta_stack_pop(Editing *ed) +{ + MetaStack *ms = SEQ_meta_stack_active_get(ed); + Sequence *meta_parent = ms->parseq; + SEQ_seqbase_active_set(ed, ms->oldbasep); + SEQ_channels_displayed_set(ed, ms->old_channels); + BLI_remlink(&ed->metastack, ms); + MEM_freeN(ms); + return meta_parent; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/sequencer/intern/strip_edit.c b/source/blender/sequencer/intern/strip_edit.c index bd439e3c9f8..4a88eab0fe2 100644 --- a/source/blender/sequencer/intern/strip_edit.c +++ b/source/blender/sequencer/intern/strip_edit.c @@ -192,19 +192,6 @@ void SEQ_edit_remove_flagged_sequences(Scene *scene, ListBase *seqbase) } } -static bool seq_exists_in_seqbase(Sequence *seq, ListBase *seqbase) -{ - LISTBASE_FOREACH (Sequence *, seq_test, seqbase) { - if (seq_test->type == SEQ_TYPE_META && seq_exists_in_seqbase(seq, &seq_test->seqbase)) { - return true; - } - if (seq_test == seq) { - return true; - } - } - return false; -} - bool SEQ_edit_move_strip_to_seqbase(Scene *scene, ListBase *seqbase, Sequence *seq, @@ -247,12 +234,12 @@ bool SEQ_edit_move_strip_to_meta(Scene *scene, return false; } - if (src_seq->type == SEQ_TYPE_META && seq_exists_in_seqbase(dst_seqm, &src_seq->seqbase)) { + if (src_seq->type == SEQ_TYPE_META && SEQ_exists_in_seqbase(dst_seqm, &src_seq->seqbase)) { *error_str = N_("Moved strip is parent of provided meta strip"); return false; } - if (!seq_exists_in_seqbase(dst_seqm, &ed->seqbase)) { + if (!SEQ_exists_in_seqbase(dst_seqm, &ed->seqbase)) { *error_str = N_("Can not move strip to different scene"); return false; } diff --git a/source/blender/sequencer/intern/strip_relations.c b/source/blender/sequencer/intern/strip_relations.c index 4acf2763ce5..a123212cb6e 100644 --- a/source/blender/sequencer/intern/strip_relations.c +++ b/source/blender/sequencer/intern/strip_relations.c @@ -457,3 +457,16 @@ struct Sequence *SEQ_find_metastrip_by_sequence(ListBase *seqbase, Sequence *met return NULL; } + +bool SEQ_exists_in_seqbase(const Sequence *seq, const ListBase *seqbase) +{ + LISTBASE_FOREACH (Sequence *, seq_test, seqbase) { + if (seq_test->type == SEQ_TYPE_META && SEQ_exists_in_seqbase(seq, &seq_test->seqbase)) { + return true; + } + if (seq_test == seq) { + return true; + } + } + return false; +} -- cgit v1.2.3