VSE: Use C++ containers for strip iteration

Use `VectorSet`, `Vector` or `Span` instead of `SeqCollection` struct.
It is now possible to use native `for` loops and `SEQ_ITERATOR_FOREACH`
macro can be removed.

Another feature is, sets of strips no longer needs to be freed. However,
this poses a limitation, that query functions can not be used in case,
where these sets need to be available outside of scope where they are
created.

Pull Request: https://projects.blender.org/blender/blender/pulls/111909
This commit is contained in:
Richard Antalik
2023-11-06 01:36:44 +01:00
committed by Richard Antalik
parent 93f6001683
commit 3fccfe0bc6
28 changed files with 582 additions and 853 deletions

View File

@@ -107,18 +107,15 @@ static int seq_frame_apply_snap(bContext *C, Scene *scene, const int timeline_fr
{
ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(scene));
SeqCollection *strips = SEQ_query_all_strips(seqbase);
int best_frame = 0;
int best_distance = MAXFRAME;
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : SEQ_query_all_strips(seqbase)) {
seq_frame_snap_update_best(
SEQ_time_left_handle_frame_get(scene, seq), timeline_frame, &best_frame, &best_distance);
seq_frame_snap_update_best(
SEQ_time_right_handle_frame_get(scene, seq), timeline_frame, &best_frame, &best_distance);
}
SEQ_collection_free(strips);
if (best_distance < seq_snap_threshold_get_frame_distance(C)) {
return best_frame;

View File

@@ -351,15 +351,13 @@ static void seq_load_apply_generic_options(bContext *C, wmOperator *op, Sequence
if (RNA_boolean_get(op->ptr, "overlap_shuffle_override")) {
/* Use set overlap_mode to fix overlaps. */
SeqCollection *strip_col = SEQ_collection_create(__func__);
SEQ_collection_append_strip(seq, strip_col);
blender::VectorSet<Sequence *> strip_col;
strip_col.add(seq);
ScrArea *area = CTX_wm_area(C);
const bool use_sync_markers = (((SpaceSeq *)area->spacedata.first)->flag & SEQ_MARKER_TRANS) !=
0;
SEQ_transform_handle_overlap(scene, ed->seqbasep, strip_col, nullptr, use_sync_markers);
SEQ_collection_free(strip_col);
SEQ_transform_handle_overlap(scene, ed->seqbasep, strip_col, use_sync_markers);
}
else {
/* Shuffle strip channel to fix overlaps. */
@@ -370,8 +368,7 @@ static void seq_load_apply_generic_options(bContext *C, wmOperator *op, Sequence
/* In this alternative version we only check for overlap, but do not do anything about them. */
static bool seq_load_apply_generic_options_only_test_overlap(bContext *C,
wmOperator *op,
Sequence *seq,
SeqCollection *strip_col)
Sequence *seq)
{
Scene *scene = CTX_data_scene(C);
Editing *ed = SEQ_editing_get(scene);
@@ -385,8 +382,6 @@ static bool seq_load_apply_generic_options_only_test_overlap(bContext *C,
SEQ_select_active_set(scene, seq);
}
SEQ_collection_append_strip(seq, strip_col);
return SEQ_transform_test_overlap(scene, ed->seqbasep, seq);
}
@@ -779,7 +774,7 @@ static IMB_Proxy_Size seq_get_proxy_size_flags(bContext *C)
return proxy_sizes;
}
static void seq_build_proxy(bContext *C, SeqCollection *movie_strips)
static void seq_build_proxy(bContext *C, blender::Span<Sequence *> movie_strips)
{
if (U.sequencer_proxy_setup != USER_SEQ_PROXY_SETUP_AUTOMATIC) {
return;
@@ -788,8 +783,7 @@ static void seq_build_proxy(bContext *C, SeqCollection *movie_strips)
wmJob *wm_job = ED_seq_proxy_wm_job_get(C);
ProxyJob *pj = ED_seq_proxy_job_get(C, wm_job);
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, movie_strips) {
for (Sequence *seq : movie_strips) {
/* Enable and set proxy size. */
SEQ_proxy_set(seq, true);
seq->strip->proxy->build_size_flags = seq_get_proxy_size_flags(C);
@@ -821,7 +815,7 @@ static void sequencer_add_movie_clamp_sound_strip_length(Scene *scene,
static void sequencer_add_movie_multiple_strips(bContext *C,
wmOperator *op,
SeqLoadData *load_data,
SeqCollection *r_movie_strips)
blender::VectorSet<Sequence *> &r_movie_strips)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
@@ -829,11 +823,7 @@ static void sequencer_add_movie_multiple_strips(bContext *C,
bool overlap_shuffle_override = RNA_boolean_get(op->ptr, "overlap") == false &&
RNA_boolean_get(op->ptr, "overlap_shuffle_override");
bool has_seq_overlap = false;
SeqCollection *strip_col = nullptr;
if (overlap_shuffle_override) {
strip_col = SEQ_collection_create(__func__);
}
blender::Vector<Sequence *> added_strips;
RNA_BEGIN (op->ptr, itemptr, "files") {
char dir_only[FILE_MAX];
@@ -854,10 +844,12 @@ static void sequencer_add_movie_multiple_strips(bContext *C,
if (RNA_boolean_get(op->ptr, "sound")) {
seq_sound = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data);
sequencer_add_movie_clamp_sound_strip_length(scene, seq_movie, seq_sound);
added_strips.append(seq_movie);
if (seq_sound) {
/* The video has sound, shift the video strip up a channel to make room for the sound
* strip. */
added_strips.append(seq_sound);
seq_movie->machine++;
}
}
@@ -865,16 +857,14 @@ static void sequencer_add_movie_multiple_strips(bContext *C,
load_data->start_frame += SEQ_time_right_handle_frame_get(scene, seq_movie) -
SEQ_time_left_handle_frame_get(scene, seq_movie);
if (overlap_shuffle_override) {
has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap(
C, op, seq_sound, strip_col);
has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap(
C, op, seq_movie, strip_col);
has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap(C, op, seq_sound);
has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap(C, op, seq_movie);
}
else {
seq_load_apply_generic_options(C, op, seq_sound);
seq_load_apply_generic_options(C, op, seq_movie);
}
SEQ_collection_append_strip(seq_movie, r_movie_strips);
r_movie_strips.add(seq_movie);
}
}
RNA_END;
@@ -884,17 +874,15 @@ static void sequencer_add_movie_multiple_strips(bContext *C,
ScrArea *area = CTX_wm_area(C);
const bool use_sync_markers = (((SpaceSeq *)area->spacedata.first)->flag &
SEQ_MARKER_TRANS) != 0;
SEQ_transform_handle_overlap(scene, ed->seqbasep, strip_col, nullptr, use_sync_markers);
SEQ_transform_handle_overlap(scene, ed->seqbasep, added_strips, use_sync_markers);
}
SEQ_collection_free(strip_col);
}
}
static bool sequencer_add_movie_single_strip(bContext *C,
wmOperator *op,
SeqLoadData *load_data,
SeqCollection *r_movie_strips)
blender::VectorSet<Sequence *> &r_movie_strips)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
@@ -902,6 +890,7 @@ static bool sequencer_add_movie_single_strip(bContext *C,
Sequence *seq_movie = nullptr;
Sequence *seq_sound = nullptr;
blender::Vector<Sequence *> added_strips;
seq_movie = SEQ_add_movie_strip(bmain, scene, ed->seqbasep, load_data);
@@ -912,7 +901,10 @@ static bool sequencer_add_movie_single_strip(bContext *C,
if (RNA_boolean_get(op->ptr, "sound")) {
seq_sound = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data);
sequencer_add_movie_clamp_sound_strip_length(scene, seq_movie, seq_sound);
added_strips.append(seq_movie);
if (seq_sound) {
added_strips.append(seq_sound);
/* The video has sound, shift the video strip up a channel to make room for the sound
* strip. */
seq_movie->machine++;
@@ -922,28 +914,23 @@ static bool sequencer_add_movie_single_strip(bContext *C,
bool overlap_shuffle_override = RNA_boolean_get(op->ptr, "overlap") == false &&
RNA_boolean_get(op->ptr, "overlap_shuffle_override");
if (overlap_shuffle_override) {
SeqCollection *strip_col = SEQ_collection_create(__func__);
bool has_seq_overlap = false;
has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap(
C, op, seq_sound, strip_col);
has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap(
C, op, seq_movie, strip_col);
has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap(C, op, seq_sound);
has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap(C, op, seq_movie);
if (has_seq_overlap) {
ScrArea *area = CTX_wm_area(C);
const bool use_sync_markers = (((SpaceSeq *)area->spacedata.first)->flag &
SEQ_MARKER_TRANS) != 0;
SEQ_transform_handle_overlap(scene, ed->seqbasep, strip_col, nullptr, use_sync_markers);
SEQ_transform_handle_overlap(scene, ed->seqbasep, added_strips, use_sync_markers);
}
SEQ_collection_free(strip_col);
}
else {
seq_load_apply_generic_options(C, op, seq_sound);
seq_load_apply_generic_options(C, op, seq_movie);
}
SEQ_collection_append_strip(seq_movie, r_movie_strips);
r_movie_strips.add(seq_movie);
return true;
}
@@ -960,7 +947,7 @@ static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op)
ED_sequencer_deselect_all(scene);
}
SeqCollection *movie_strips = SEQ_collection_create(__func__);
blender::VectorSet<Sequence *> movie_strips;
const int tot_files = RNA_property_collection_length(op->ptr,
RNA_struct_find_property(op->ptr, "files"));
if (tot_files > 1) {
@@ -970,9 +957,8 @@ static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op)
sequencer_add_movie_single_strip(C, op, &load_data, movie_strips);
}
if (SEQ_collection_len(movie_strips) == 0) {
if (movie_strips.is_empty()) {
sequencer_add_cancel(C, op);
SEQ_collection_free(movie_strips);
return OPERATOR_CANCELLED;
}
@@ -983,7 +969,6 @@ static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op)
/* Free custom data. */
sequencer_add_cancel(C, op);
SEQ_collection_free(movie_strips);
return OPERATOR_FINISHED;
}

View File

@@ -299,20 +299,18 @@ static void sequencer_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop)
ListBase *channels = SEQ_channels_displayed_get(ed);
SpaceSeq *sseq = CTX_wm_space_seq(C);
SeqCollection *strips = SEQ_query_rendered_strips(
blender::VectorSet strips = SEQ_query_rendered_strips(
scene, channels, seqbase, scene->r.cfra, sseq->chanshown);
/* Get the top most strip channel that is in view. */
Sequence *seq;
int max_channel = -1;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
max_channel = max_ii(seq->machine, max_channel);
}
if (max_channel != -1) {
RNA_int_set(drop->ptr, "channel", max_channel);
}
SEQ_collection_free(strips);
}
}

View File

@@ -1733,10 +1733,7 @@ static int sequencer_delete_exec(bContext *C, wmOperator *op)
SEQ_prefetch_stop(scene);
SeqCollection *selected_strips = selected_strips_from_context(C);
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, selected_strips) {
for (Sequence *seq : selected_strips_from_context(C)) {
SEQ_edit_flag_for_removal(scene, seqbasep, seq);
if (delete_data) {
sequencer_delete_strip_data(C, seq);
@@ -1744,8 +1741,6 @@ static int sequencer_delete_exec(bContext *C, wmOperator *op)
}
SEQ_edit_remove_flagged_sequences(scene, seqbasep);
SEQ_collection_free(selected_strips);
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);

View File

@@ -9,6 +9,7 @@
#pragma once
#include "BLI_vector.hh"
#include "BLI_vector_set.hh"
#include "DNA_sequence_types.h"
#include "RNA_access.hh"
@@ -21,7 +22,6 @@ struct wmGizmoGroupType;
struct wmGizmoType;
struct Main;
struct Scene;
struct SeqCollection;
struct SeqRetimingKey;
struct Sequence;
struct SpaceSeq;
@@ -153,7 +153,7 @@ bool sequencer_view_strips_poll(bContext *C);
* \param C: context
* \return collection of strips (`Sequence`)
*/
SeqCollection *all_strips_from_context(bContext *C);
blender::VectorSet<Sequence *> all_strips_from_context(bContext *C);
/**
* Returns collection with selected strips presented to user. If operation is done in preview,
@@ -163,7 +163,7 @@ SeqCollection *all_strips_from_context(bContext *C);
* \param C: context
* \return collection of strips (`Sequence`)
*/
SeqCollection *selected_strips_from_context(bContext *C);
blender::VectorSet<Sequence *> selected_strips_from_context(bContext *C);
/* Externals. */

View File

@@ -797,14 +797,12 @@ void sequencer_draw_preview(const bContext *C,
if (!draw_backdrop && scene->ed != nullptr) {
Editing *ed = SEQ_editing_get(scene);
ListBase *channels = SEQ_channels_displayed_get(ed);
SeqCollection *collection = SEQ_query_rendered_strips(
blender::VectorSet strips = SEQ_query_rendered_strips(
scene, channels, ed->seqbasep, timeline_frame, 0);
Sequence *seq;
Sequence *active_seq = SEQ_select_active_get(scene);
SEQ_ITERATOR_FOREACH (seq, collection) {
for (Sequence *seq : strips) {
seq_draw_image_origin_and_outline(C, seq, seq == active_seq);
}
SEQ_collection_free(collection);
}
if (draw_gpencil && show_imbuf && (sseq->flag & SEQ_SHOW_OVERLAY)) {

View File

@@ -148,14 +148,13 @@ static bool retiming_poll(bContext *C)
static void retiming_key_overlap(Scene *scene, Sequence *seq)
{
ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(scene));
SeqCollection *strips = SEQ_collection_create(__func__);
SEQ_collection_append_strip(seq, strips);
SeqCollection *dependant = SEQ_collection_create(__func__);
SEQ_collection_expand(scene, seqbase, strips, SEQ_query_strip_effect_chain);
SEQ_collection_remove_strip(seq, dependant);
blender::VectorSet<Sequence *> strips;
blender::VectorSet<Sequence *> dependant;
strips.add(seq);
dependant.add(seq);
SEQ_iterator_set_expand(scene, seqbase, dependant, SEQ_query_strip_effect_chain);
dependant.remove(seq);
SEQ_transform_handle_overlap(scene, seqbase, strips, dependant, true);
SEQ_collection_free(strips);
SEQ_collection_free(dependant);
}
/*-------------------------------------------------------------------- */
@@ -222,13 +221,12 @@ static bool retiming_key_add_new_for_seq(bContext *C,
static int retiming_key_add_from_selection(bContext *C,
wmOperator *op,
SeqCollection *strips,
blender::Span<Sequence *> strips,
const int timeline_frame)
{
bool inserted = false;
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
inserted |= retiming_key_add_new_for_seq(C, op, seq, timeline_frame);
}
@@ -268,14 +266,13 @@ static int sequencer_retiming_key_add_exec(bContext *C, wmOperator *op)
}
int ret_val;
SeqCollection *strips = selected_strips_from_context(C);
if (SEQ_collection_len(strips) != 0) {
blender::VectorSet<Sequence *> strips = selected_strips_from_context(C);
if (!strips.is_empty()) {
ret_val = retiming_key_add_from_selection(C, op, strips, timeline_frame);
}
else {
ret_val = retiming_key_add_to_editable_strips(C, op, timeline_frame);
}
SEQ_collection_free(strips);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return ret_val;
@@ -352,16 +349,14 @@ static bool freeze_frame_add_from_strip_selection(bContext *C,
const int duration)
{
Scene *scene = CTX_data_scene(C);
SeqCollection *strips = selected_strips_from_context(C);
blender::VectorSet<Sequence *> strips = selected_strips_from_context(C);
const int timeline_frame = BKE_scene_frame_get(scene);
bool success = false;
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
success |= freeze_frame_add_new_for_seq(C, op, seq, timeline_frame, duration);
SEQ_relations_invalidate_cache_raw(scene, seq);
}
SEQ_collection_free(strips);
return success;
}
@@ -543,10 +538,9 @@ static SeqRetimingKey *ensure_left_and_right_keys(const bContext *C, Sequence *s
static int strip_speed_set_exec(bContext *C, const wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
SeqCollection *strips = selected_strips_from_context(C);
blender::VectorSet<Sequence *> strips = selected_strips_from_context(C);
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
SEQ_retiming_data_ensure(seq);
SeqRetimingKey *key = ensure_left_and_right_keys(C, seq);
@@ -557,7 +551,6 @@ static int strip_speed_set_exec(bContext *C, const wmOperator *op)
SEQ_retiming_key_speed_set(scene, seq, key, RNA_float_get(op->ptr, "speed"));
SEQ_relations_invalidate_cache_raw(scene, seq);
}
SEQ_collection_free(strips);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -811,12 +804,11 @@ int sequencer_retiming_select_all_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
int action = RNA_enum_get(op->ptr, "action");
SeqCollection *strips = all_strips_from_context(C);
Sequence *seq;
blender::VectorSet<Sequence *> strips = all_strips_from_context(C);
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
if (!SEQ_retiming_data_is_editable(seq)) {
continue;
}
@@ -833,7 +825,7 @@ int sequencer_retiming_select_all_exec(bContext *C, wmOperator *op)
SEQ_retiming_selection_clear(SEQ_editing_get(scene));
}
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
if (!SEQ_retiming_data_is_editable(seq)) {
continue;
}

View File

@@ -54,7 +54,7 @@
/** \name Selection Utilities
* \{ */
SeqCollection *all_strips_from_context(bContext *C)
blender::VectorSet<Sequence *> all_strips_from_context(bContext *C)
{
Scene *scene = CTX_data_scene(C);
Editing *ed = SEQ_editing_get(scene);
@@ -69,7 +69,7 @@ SeqCollection *all_strips_from_context(bContext *C)
return SEQ_query_all_strips(seqbase);
}
SeqCollection *selected_strips_from_context(bContext *C)
blender::VectorSet<Sequence *> selected_strips_from_context(bContext *C)
{
Scene *scene = CTX_data_scene(C);
Editing *ed = SEQ_editing_get(scene);
@@ -77,9 +77,11 @@ SeqCollection *selected_strips_from_context(bContext *C)
ListBase *channels = SEQ_channels_displayed_get(ed);
const bool is_preview = sequencer_view_has_preview_poll(C);
if (is_preview) {
SeqCollection *strips = SEQ_query_rendered_strips(scene, channels, seqbase, scene->r.cfra, 0);
SEQ_filter_selected_strips(strips);
blender::VectorSet strips = SEQ_query_rendered_strips(
scene, channels, seqbase, scene->r.cfra, 0);
strips.remove_if([&](Sequence *seq) { return (seq->flag & SELECT) == 0; });
return strips;
}
@@ -448,12 +450,11 @@ static int sequencer_de_select_all_exec(bContext *C, wmOperator *op)
return sequencer_retiming_select_all_exec(C, op);
}
SeqCollection *strips = all_strips_from_context(C);
Sequence *seq;
blender::VectorSet strips = all_strips_from_context(C);
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
if (seq->flag & SEQ_ALLSEL) {
action = SEL_DESELECT;
break;
@@ -461,7 +462,7 @@ static int sequencer_de_select_all_exec(bContext *C, wmOperator *op)
}
}
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
switch (action) {
case SEL_SELECT:
seq->flag &= ~(SEQ_LEFTSEL + SEQ_RIGHTSEL);
@@ -481,9 +482,6 @@ static int sequencer_de_select_all_exec(bContext *C, wmOperator *op)
break;
}
}
SEQ_collection_free(strips);
ED_outliner_select_sync_from_sequence_tag(C);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
@@ -521,10 +519,9 @@ static int sequencer_select_inverse_exec(bContext *C, wmOperator * /*op*/)
return OPERATOR_CANCELLED;
}
SeqCollection *strips = all_strips_from_context(C);
Sequence *seq;
blender::VectorSet strips = all_strips_from_context(C);
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
if (seq->flag & SELECT) {
seq->flag &= ~SEQ_ALLSEL;
}
@@ -534,8 +531,6 @@ static int sequencer_select_inverse_exec(bContext *C, wmOperator * /*op*/)
}
}
SEQ_collection_free(strips);
ED_outliner_select_sync_from_sequence_tag(C);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
@@ -750,9 +745,6 @@ static Sequence *seq_select_seq_from_preview(
/* Always update the coordinates (check extended after). */
const bool use_cycle = (!WM_cursor_test_motion_and_update(mval) || extend || toggle);
SeqCollection *strips = SEQ_query_rendered_strips(
scene, channels, seqbase, scene->r.cfra, sseq->chanshown);
/* Allow strips this far from the closest center to be included.
* This allows cycling over center points which are near enough
* to overlapping from the users perspective. */
@@ -762,11 +754,13 @@ static Sequence *seq_select_seq_from_preview(
UI_view2d_scale_get_y(v2d),
};
blender::VectorSet strips = SEQ_query_rendered_strips(
scene, channels, seqbase, scene->r.cfra, sseq->chanshown);
SeqSelect_Link *slink_active = nullptr;
Sequence *seq_active = SEQ_select_active_get(scene);
ListBase strips_ordered = {nullptr};
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
bool isect = false;
float center_dist_sq_test = 0.0f;
if (center) {
@@ -799,7 +793,6 @@ static Sequence *seq_select_seq_from_preview(
}
}
}
SEQ_collection_free(strips);
BLI_listbase_sort(&strips_ordered,
center ? seq_sort_for_center_select : seq_sort_for_depth_select);
@@ -1635,10 +1628,9 @@ static void seq_box_select_seq_from_preview(const bContext *C, rctf *rect, const
ListBase *channels = SEQ_channels_displayed_get(ed);
SpaceSeq *sseq = CTX_wm_space_seq(C);
SeqCollection *strips = SEQ_query_rendered_strips(
blender::VectorSet strips = SEQ_query_rendered_strips(
scene, channels, seqbase, scene->r.cfra, sseq->chanshown);
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
if (!seq_box_select_rect_image_isect(scene, seq, rect)) {
continue;
}
@@ -1651,8 +1643,6 @@ static void seq_box_select_seq_from_preview(const bContext *C, rctf *rect, const
seq->flag &= ~SELECT;
}
}
SEQ_collection_free(strips);
}
static int sequencer_box_select_exec(bContext *C, wmOperator *op)
@@ -1859,15 +1849,14 @@ static const EnumPropertyItem sequencer_prop_select_grouped_types[] = {
#define SEQ_CHANNEL_CHECK(_seq, _chan) ELEM((_chan), 0, (_seq)->machine)
static bool select_grouped_type(SeqCollection *strips,
static bool select_grouped_type(blender::Span<Sequence *> strips,
ListBase * /*seqbase*/,
Sequence *actseq,
const int channel)
{
bool changed = false;
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == actseq->type) {
seq->flag |= SELECT;
changed = true;
@@ -1877,7 +1866,7 @@ static bool select_grouped_type(SeqCollection *strips,
return changed;
}
static bool select_grouped_type_basic(SeqCollection *strips,
static bool select_grouped_type_basic(blender::Span<Sequence *> strips,
ListBase * /*seqbase*/,
Sequence *actseq,
const int channel)
@@ -1885,8 +1874,7 @@ static bool select_grouped_type_basic(SeqCollection *strips,
bool changed = false;
const bool is_sound = SEQ_IS_SOUND(actseq);
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
if (SEQ_CHANNEL_CHECK(seq, channel) && (is_sound ? SEQ_IS_SOUND(seq) : !SEQ_IS_SOUND(seq))) {
seq->flag |= SELECT;
changed = true;
@@ -1896,7 +1884,7 @@ static bool select_grouped_type_basic(SeqCollection *strips,
return changed;
}
static bool select_grouped_type_effect(SeqCollection *strips,
static bool select_grouped_type_effect(blender::Span<Sequence *> strips,
ListBase * /*seqbase*/,
Sequence *actseq,
const int channel)
@@ -1904,8 +1892,7 @@ static bool select_grouped_type_effect(SeqCollection *strips,
bool changed = false;
const bool is_effect = SEQ_IS_EFFECT(actseq);
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
if (SEQ_CHANNEL_CHECK(seq, channel) && (is_effect ? SEQ_IS_EFFECT(seq) : !SEQ_IS_EFFECT(seq)))
{
seq->flag |= SELECT;
@@ -1916,7 +1903,7 @@ static bool select_grouped_type_effect(SeqCollection *strips,
return changed;
}
static bool select_grouped_data(SeqCollection *strips,
static bool select_grouped_data(blender::Span<Sequence *> strips,
ListBase * /*seqbase*/,
Sequence *actseq,
const int channel)
@@ -1928,10 +1915,8 @@ static bool select_grouped_data(SeqCollection *strips,
return changed;
}
Sequence *seq;
if (SEQ_HAS_PATH(actseq) && dirpath) {
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
if (SEQ_CHANNEL_CHECK(seq, channel) && SEQ_HAS_PATH(seq) && seq->strip &&
STREQ(seq->strip->dirpath, dirpath))
{
@@ -1942,7 +1927,7 @@ static bool select_grouped_data(SeqCollection *strips,
}
else if (actseq->type == SEQ_TYPE_SCENE) {
Scene *sce = actseq->scene;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == SEQ_TYPE_SCENE && seq->scene == sce) {
seq->flag |= SELECT;
changed = true;
@@ -1951,7 +1936,7 @@ static bool select_grouped_data(SeqCollection *strips,
}
else if (actseq->type == SEQ_TYPE_MOVIECLIP) {
MovieClip *clip = actseq->clip;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == SEQ_TYPE_MOVIECLIP && seq->clip == clip)
{
seq->flag |= SELECT;
@@ -1961,7 +1946,7 @@ static bool select_grouped_data(SeqCollection *strips,
}
else if (actseq->type == SEQ_TYPE_MASK) {
Mask *mask = actseq->mask;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == SEQ_TYPE_MASK && seq->mask == mask) {
seq->flag |= SELECT;
changed = true;
@@ -1972,7 +1957,7 @@ static bool select_grouped_data(SeqCollection *strips,
return changed;
}
static bool select_grouped_effect(SeqCollection *strips,
static bool select_grouped_effect(blender::Span<Sequence *> strips,
ListBase * /*seqbase*/,
Sequence *actseq,
const int channel)
@@ -1984,8 +1969,7 @@ static bool select_grouped_effect(SeqCollection *strips,
effects[i] = false;
}
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
if (SEQ_CHANNEL_CHECK(seq, channel) && (seq->type & SEQ_TYPE_EFFECT) &&
SEQ_relation_is_effect_of_strip(seq, actseq))
{
@@ -1993,7 +1977,7 @@ static bool select_grouped_effect(SeqCollection *strips,
}
}
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
if (SEQ_CHANNEL_CHECK(seq, channel) && effects[seq->type]) {
if (seq->seq1) {
seq->seq1->flag |= SELECT;
@@ -2012,14 +1996,13 @@ static bool select_grouped_effect(SeqCollection *strips,
}
static bool select_grouped_time_overlap(const Scene *scene,
SeqCollection *strips,
blender::Span<Sequence *> strips,
ListBase * /*seqbase*/,
Sequence *actseq)
{
bool changed = false;
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
if (SEQ_time_left_handle_frame_get(scene, seq) <
SEQ_time_right_handle_frame_get(scene, actseq) &&
SEQ_time_right_handle_frame_get(scene, seq) >
@@ -2037,7 +2020,7 @@ static bool select_grouped_time_overlap(const Scene *scene,
static void query_lower_channel_strips(const Scene *scene,
Sequence *seq_reference,
ListBase *seqbase,
SeqCollection *collection)
blender::VectorSet<Sequence *> &strips)
{
LISTBASE_FOREACH (Sequence *, seq_test, seqbase) {
if (seq_test->machine > seq_reference->machine) {
@@ -2050,32 +2033,31 @@ static void query_lower_channel_strips(const Scene *scene,
{
continue; /* Not intersecting in time. */
}
SEQ_collection_append_strip(seq_test, collection);
strips.add(seq_test);
}
}
/* Select all strips within time range and with lower channel of initial selection. Then select
* effect chains of these strips. */
static bool select_grouped_effect_link(const Scene *scene,
SeqCollection *strips,
blender::VectorSet<Sequence *> strips,
ListBase *seqbase,
Sequence * /*actseq*/,
const int /*channel*/)
{
/* Get collection of strips. */
SEQ_filter_selected_strips(strips);
const int selected_strip_count = SEQ_collection_len(strips);
strips.remove_if([&](Sequence *seq) { return (seq->flag & SELECT) == 0; });
const int selected_strip_count = strips.size();
/* XXX: this uses scene as arg, so it does not work with iterator :( I had thought about this,
* but expand function is just so useful... I can just add scene and inject it I guess. */
SEQ_collection_expand(scene, seqbase, strips, query_lower_channel_strips);
SEQ_collection_expand(scene, seqbase, strips, SEQ_query_strip_effect_chain);
SEQ_iterator_set_expand(scene, seqbase, strips, query_lower_channel_strips);
SEQ_iterator_set_expand(scene, seqbase, strips, SEQ_query_strip_effect_chain);
/* Check if other strips will be affected. */
const bool changed = SEQ_collection_len(strips) > selected_strip_count;
const bool changed = strips.size() > selected_strip_count;
/* Actual logic. */
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
seq->flag |= SELECT;
}
@@ -2097,9 +2079,9 @@ static int sequencer_select_grouped_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
SeqCollection *strips = all_strips_from_context(C);
blender::VectorSet strips = all_strips_from_context(C);
if (actseq == nullptr || (is_preview && !SEQ_collection_has_strip(actseq, strips))) {
if (actseq == nullptr || (is_preview && !strips.contains(actseq))) {
BKE_report(op->reports, RPT_ERROR, "No active sequence!");
return OPERATOR_CANCELLED;
}
@@ -2144,8 +2126,6 @@ static int sequencer_select_grouped_exec(bContext *C, wmOperator *op)
break;
}
SEQ_collection_free(strips);
if (changed) {
ED_outliner_select_sync_from_sequence_tag(C);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);

View File

@@ -271,7 +271,9 @@ void SEQUENCER_OT_view_zoom_ratio(wmOperatorType *ot)
/** \name Frame Selected Operator
* \{ */
static void seq_view_collection_rect_preview(Scene *scene, SeqCollection *strips, rctf *rect)
static void seq_view_collection_rect_preview(Scene *scene,
blender::Span<Sequence *> strips,
rctf *rect)
{
float min[2], max[2];
SEQ_image_transform_bounding_box_from_collection(scene, strips, true, min, max);
@@ -292,10 +294,10 @@ static void seq_view_collection_rect_preview(Scene *scene, SeqCollection *strips
BLI_rctf_scale(rect, 1.1f);
}
static void seq_view_collection_rect_timeline(Scene *scene, SeqCollection *strips, rctf *rect)
static void seq_view_collection_rect_timeline(Scene *scene,
blender::Span<Sequence *> strips,
rctf *rect)
{
Sequence *seq;
int xmin = MAXFRAME * 2;
int xmax = -MAXFRAME * 2;
int ymin = MAXSEQ + 1;
@@ -305,7 +307,7 @@ static void seq_view_collection_rect_timeline(Scene *scene, SeqCollection *strip
int ymargin = 1;
int xmargin = FPS;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
xmin = min_ii(xmin, SEQ_time_left_handle_frame_get(scene, seq));
xmax = max_ii(xmax, SEQ_time_right_handle_frame_get(scene, seq));
@@ -339,11 +341,11 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
ARegion *region = CTX_wm_region(C);
SeqCollection *strips = selected_strips_from_context(C);
blender::VectorSet strips = selected_strips_from_context(C);
View2D *v2d = UI_view2d_fromcontext(C);
rctf cur_new = v2d->cur;
if (SEQ_collection_len(strips) == 0) {
if (strips.is_empty()) {
return OPERATOR_CANCELLED;
}

View File

@@ -69,7 +69,7 @@ struct TransSeq {
View2DEdgePanData edge_pan;
/* Strips that aren't selected, but their position entirely depends on transformed strips. */
SeqCollection *time_dependent_strips;
blender::VectorSet<Sequence *> time_dependent_strips;
};
/* -------------------------------------------------------------------- */
@@ -264,20 +264,18 @@ static void free_transform_custom_data(TransCustomData *custom_data)
{
if ((custom_data->data != nullptr) && custom_data->use_free) {
TransSeq *ts = static_cast<TransSeq *>(custom_data->data);
SEQ_collection_free(ts->time_dependent_strips);
MEM_freeN(ts->tdseq);
MEM_freeN(custom_data->data);
MEM_delete(ts);
custom_data->data = nullptr;
}
}
/* Canceled, need to update the strips display. */
static void seq_transform_cancel(TransInfo *t, SeqCollection *transformed_strips)
static void seq_transform_cancel(TransInfo *t, blender::Span<Sequence *> transformed_strips)
{
ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(t->scene));
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, transformed_strips) {
for (Sequence *seq : transformed_strips) {
/* Handle pre-existing overlapping strips even when operator is canceled.
* This is necessary for SEQUENCER_OT_duplicate_move macro for example. */
if (SEQ_transform_test_overlap(t->scene, seqbase, seq)) {
@@ -292,10 +290,9 @@ static ListBase *seqbase_active_get(const TransInfo *t)
return SEQ_active_seqbase_get(ed);
}
static bool seq_transform_check_overlap(SeqCollection *transformed_strips)
static bool seq_transform_check_overlap(blender::Span<Sequence *> transformed_strips)
{
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, transformed_strips) {
for (Sequence *seq : transformed_strips) {
if (seq->flag & SEQ_OVERLAP) {
return true;
}
@@ -303,15 +300,16 @@ static bool seq_transform_check_overlap(SeqCollection *transformed_strips)
return false;
}
static SeqCollection *seq_transform_collection_from_transdata(TransDataContainer *tc)
static blender::VectorSet<Sequence *> seq_transform_collection_from_transdata(
TransDataContainer *tc)
{
SeqCollection *collection = SEQ_collection_create(__func__);
blender::VectorSet<Sequence *> strips;
TransData *td = tc->data;
for (int a = 0; a < tc->data_len; a++, td++) {
Sequence *seq = ((TransDataSeq *)td->extra)->seq;
SEQ_collection_append_strip(seq, collection);
strips.add(seq);
}
return collection;
return strips;
}
static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data)
@@ -322,18 +320,16 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c
return;
}
SeqCollection *transformed_strips = seq_transform_collection_from_transdata(tc);
SEQ_collection_expand(
blender::VectorSet transformed_strips = seq_transform_collection_from_transdata(tc);
SEQ_iterator_set_expand(
t->scene, seqbase_active_get(t), transformed_strips, SEQ_query_strip_effect_chain);
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, transformed_strips) {
for (Sequence *seq : transformed_strips) {
seq->flag &= ~SEQ_IGNORE_CHANNEL_LOCK;
}
if (t->state == TRANS_CANCEL) {
seq_transform_cancel(t, transformed_strips);
SEQ_collection_free(transformed_strips);
free_transform_custom_data(custom_data);
return;
}
@@ -348,17 +344,16 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c
scene, seqbasep, transformed_strips, ts->time_dependent_strips, use_sync_markers);
}
SEQ_collection_free(transformed_strips);
DEG_id_tag_update(&t->scene->id, ID_RECALC_SEQUENCER_STRIPS);
free_transform_custom_data(custom_data);
}
static SeqCollection *query_selected_strips_no_handles(ListBase *seqbase)
static blender::VectorSet<Sequence *> query_selected_strips_no_handles(ListBase *seqbase)
{
SeqCollection *strips = SEQ_collection_create(__func__);
blender::VectorSet<Sequence *> strips;
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
if ((seq->flag & SELECT) != 0 && ((seq->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) == 0)) {
SEQ_collection_append_strip(seq, strips);
strips.add(seq);
}
}
return strips;
@@ -393,10 +388,11 @@ static Sequence *effect_base_input_get(const Scene *scene, Sequence *effect, Seq
}
/**
* Strips that aren't selected, but their position entirely depends on transformed strips.
* This collection is used to offset animation.
* Strips that aren't stime_dependent_stripselected, but their position entirely depends on
* transformed strips. This collection is used to offset animation.
*/
static SeqCollection *query_time_dependent_strips_strips(TransInfo *t)
static void query_time_dependent_strips_strips(
TransInfo *t, blender::VectorSet<Sequence *> &time_dependent_strips)
{
ListBase *seqbase = seqbase_active_get(t);
@@ -404,42 +400,38 @@ static SeqCollection *query_time_dependent_strips_strips(TransInfo *t)
* If all inputs of any effect even indirectly(through another effect) points to selected strip,
* its position will change. */
SeqCollection *strips_no_handles = query_selected_strips_no_handles(seqbase);
/* Selection is needed as reference for related strips. */
SeqCollection *dependent = SEQ_collection_duplicate(strips_no_handles);
SEQ_collection_expand(t->scene, seqbase, strips_no_handles, SEQ_query_strip_effect_chain);
blender::VectorSet<Sequence *> strips_no_handles = query_selected_strips_no_handles(seqbase);
time_dependent_strips.add_multiple(strips_no_handles);
SEQ_iterator_set_expand(t->scene, seqbase, strips_no_handles, SEQ_query_strip_effect_chain);
bool strip_added = true;
while (strip_added) {
strip_added = false;
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips_no_handles) {
if (SEQ_collection_has_strip(seq, dependent)) {
for (Sequence *seq : strips_no_handles) {
if (time_dependent_strips.contains(seq)) {
continue; /* Strip is already in collection, skip it. */
}
/* If both seq1 and seq2 exist, both must be selected. */
if (seq->seq1 && SEQ_collection_has_strip(seq->seq1, dependent)) {
if (seq->seq2 && !SEQ_collection_has_strip(seq->seq2, dependent)) {
if (seq->seq1 && time_dependent_strips.contains(seq->seq1)) {
if (seq->seq2 && !time_dependent_strips.contains(seq->seq2)) {
continue;
}
strip_added = true;
SEQ_collection_append_strip(seq, dependent);
time_dependent_strips.add(seq);
}
}
}
SEQ_collection_free(strips_no_handles);
/* Query dependent strips where used strips do have handles selected.
* If any 2-input effect changes position because handles were moved, animation should be offset.
* With single input effect, it is less likely desirable to move animation. */
SeqCollection *selected_strips = SEQ_query_selected_strips(seqbase);
SEQ_collection_expand(t->scene, seqbase, selected_strips, SEQ_query_strip_effect_chain);
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, selected_strips) {
blender::VectorSet selected_strips = SEQ_query_selected_strips(seqbase);
SEQ_iterator_set_expand(t->scene, seqbase, selected_strips, SEQ_query_strip_effect_chain);
for (Sequence *seq : selected_strips) {
/* Check only 2 input effects. */
if (seq->seq1 == nullptr || seq->seq2 == nullptr) {
continue;
@@ -450,19 +442,13 @@ static SeqCollection *query_time_dependent_strips_strips(TransInfo *t)
Sequence *input_right = effect_base_input_get(t->scene, seq, SEQ_INPUT_RIGHT);
if ((input_left->flag & SEQ_RIGHTSEL) != 0 && (input_right->flag & SEQ_LEFTSEL) != 0) {
SEQ_collection_append_strip(seq, dependent);
time_dependent_strips.add(seq);
}
}
SEQ_collection_free(selected_strips);
/* Remove all non-effects. */
SEQ_ITERATOR_FOREACH (seq, dependent) {
if (SEQ_transform_sequence_can_be_translated(seq)) {
SEQ_collection_remove_strip(seq, dependent);
}
}
return dependent;
time_dependent_strips.remove_if(
[&](Sequence *seq) { return SEQ_transform_sequence_can_be_translated(seq); });
}
static void createTransSeqData(bContext * /*C*/, TransInfo *t)
@@ -501,7 +487,7 @@ static void createTransSeqData(bContext * /*C*/, TransInfo *t)
return;
}
tc->custom.type.data = ts = static_cast<TransSeq *>(MEM_callocN(sizeof(TransSeq), "transseq"));
tc->custom.type.data = ts = MEM_new<TransSeq>(__func__);
tc->custom.type.use_free = true;
td = tc->data = static_cast<TransData *>(
MEM_callocN(tc->data_len * sizeof(TransData), "TransSeq TransData"));
@@ -533,7 +519,7 @@ static void createTransSeqData(bContext * /*C*/, TransInfo *t)
}
}
ts->time_dependent_strips = query_time_dependent_strips_strips(t);
query_time_dependent_strips_strips(t, ts->time_dependent_strips);
}
/** \} */
@@ -639,25 +625,23 @@ static void flushTransSeq(TransInfo *t)
TransSeq *ts = (TransSeq *)TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->custom.type.data;
/* Update animation for effects. */
SEQ_ITERATOR_FOREACH (seq, ts->time_dependent_strips) {
for (Sequence *seq : ts->time_dependent_strips) {
SEQ_offset_animdata(t->scene, seq, max_offset);
}
/* need to do the overlap check in a new loop otherwise adjacent strips
* will not be updated and we'll get false positives */
SeqCollection *transformed_strips = seq_transform_collection_from_transdata(tc);
SEQ_collection_expand(
blender::VectorSet transformed_strips = seq_transform_collection_from_transdata(tc);
SEQ_iterator_set_expand(
t->scene, seqbase_active_get(t), transformed_strips, SEQ_query_strip_effect_chain);
SEQ_ITERATOR_FOREACH (seq, transformed_strips) {
for (Sequence *seq : transformed_strips) {
/* test overlap, displays red outline */
seq->flag &= ~SEQ_OVERLAP;
if (SEQ_transform_test_overlap(scene, seqbasep, seq)) {
seq->flag |= SEQ_OVERLAP;
}
}
SEQ_collection_free(transformed_strips);
}
static void recalcData_sequencer(TransInfo *t)

View File

@@ -128,20 +128,18 @@ static void createTransSeqImageData(bContext * /*C*/, TransInfo *t)
ListBase *seqbase = SEQ_active_seqbase_get(ed);
ListBase *channels = SEQ_channels_displayed_get(ed);
SeqCollection *strips = SEQ_query_rendered_strips(
blender::VectorSet strips = SEQ_query_rendered_strips(
t->scene, channels, seqbase, t->scene->r.cfra, 0);
SEQ_filter_selected_strips(strips);
strips.remove_if([&](Sequence *seq) { return (seq->flag & SELECT) == 0; });
const int count = SEQ_collection_len(strips);
if (count == 0) {
SEQ_collection_free(strips);
if (strips.is_empty()) {
return;
}
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
tc->custom.type.free_cb = freeSeqData;
tc->data_len = count * 3; /* 3 vertices per sequence are needed. */
tc->data_len = strips.size() * 3; /* 3 vertices per sequence are needed. */
TransData *td = tc->data = static_cast<TransData *>(
MEM_callocN(tc->data_len * sizeof(TransData), "TransSeq TransData"));
TransData2D *td2d = tc->data_2d = static_cast<TransData2D *>(
@@ -149,8 +147,7 @@ static void createTransSeqImageData(bContext * /*C*/, TransInfo *t)
TransDataSeq *tdseq = static_cast<TransDataSeq *>(
MEM_callocN(tc->data_len * sizeof(TransDataSeq), "TransSeq TransDataSeq"));
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
/* One `Sequence` needs 3 `TransData` entries - center point placed in image origin, then 2
* points offset by 1 in X and Y direction respectively, so rotation and scale can be
* calculated from these points. */
@@ -158,8 +155,6 @@ static void createTransSeqImageData(bContext * /*C*/, TransInfo *t)
SeqToTransData(t->scene, seq, td++, td2d++, tdseq++, 1);
SeqToTransData(t->scene, seq, td++, td2d++, tdseq++, 2);
}
SEQ_collection_free(strips);
}
static bool autokeyframe_sequencer_image(bContext *C,

View File

@@ -249,15 +249,15 @@ static bool gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min
Editing *ed = SEQ_editing_get(scene);
ListBase *seqbase = SEQ_active_seqbase_get(ed);
ListBase *channels = SEQ_channels_displayed_get(ed);
SeqCollection *strips = SEQ_query_rendered_strips(scene, channels, seqbase, scene->r.cfra, 0);
SEQ_filter_selected_strips(strips);
int selected_strips = SEQ_collection_len(strips);
blender::VectorSet strips = SEQ_query_rendered_strips(
scene, channels, seqbase, scene->r.cfra, 0);
strips.remove_if([&](Sequence *seq) { return (seq->flag & SELECT) == 0; });
int selected_strips = strips.size();
if (selected_strips > 0) {
has_select = true;
SEQ_image_transform_bounding_box_from_collection(
scene, strips, selected_strips != 1, r_min, r_max);
}
SEQ_collection_free(strips);
if (selected_strips > 1) {
/* Don't draw the cage as transforming multiple strips isn't currently very useful as it
* doesn't behave as one would expect.
@@ -301,11 +301,11 @@ static int gizmo2d_calc_transform_orientation(const bContext *C)
Editing *ed = SEQ_editing_get(scene);
ListBase *seqbase = SEQ_active_seqbase_get(ed);
ListBase *channels = SEQ_channels_displayed_get(ed);
SeqCollection *strips = SEQ_query_rendered_strips(scene, channels, seqbase, scene->r.cfra, 0);
SEQ_filter_selected_strips(strips);
blender::VectorSet strips = SEQ_query_rendered_strips(
scene, channels, seqbase, scene->r.cfra, 0);
strips.remove_if([&](Sequence *seq) { return (seq->flag & SELECT) == 0; });
bool use_local_orient = SEQ_collection_len(strips) == 1;
SEQ_collection_free(strips);
bool use_local_orient = strips.size() == 1;
if (use_local_orient) {
return V3D_ORIENT_LOCAL;
@@ -324,22 +324,20 @@ static float gizmo2d_calc_rotation(const bContext *C)
Editing *ed = SEQ_editing_get(scene);
ListBase *seqbase = SEQ_active_seqbase_get(ed);
ListBase *channels = SEQ_channels_displayed_get(ed);
SeqCollection *strips = SEQ_query_rendered_strips(scene, channels, seqbase, scene->r.cfra, 0);
SEQ_filter_selected_strips(strips);
blender::VectorSet strips = SEQ_query_rendered_strips(
scene, channels, seqbase, scene->r.cfra, 0);
strips.remove_if([&](Sequence *seq) { return (seq->flag & SELECT) == 0; });
if (SEQ_collection_len(strips) == 1) {
if (strips.size() == 1) {
/* Only return the strip rotation if only one is selected. */
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
StripTransform *transform = seq->strip->transform;
float mirror[2];
SEQ_image_transform_mirror_factor_get(seq, mirror);
SEQ_collection_free(strips);
return transform->rotation * mirror[0] * mirror[1];
}
}
SEQ_collection_free(strips);
return 0.0f;
}
@@ -350,21 +348,20 @@ static bool seq_get_strip_pivot_median(const Scene *scene, float r_pivot[2])
Editing *ed = SEQ_editing_get(scene);
ListBase *seqbase = SEQ_active_seqbase_get(ed);
ListBase *channels = SEQ_channels_displayed_get(ed);
SeqCollection *strips = SEQ_query_rendered_strips(scene, channels, seqbase, scene->r.cfra, 0);
SEQ_filter_selected_strips(strips);
bool has_select = SEQ_collection_len(strips) != 0;
blender::VectorSet strips = SEQ_query_rendered_strips(
scene, channels, seqbase, scene->r.cfra, 0);
strips.remove_if([&](Sequence *seq) { return (seq->flag & SELECT) == 0; });
bool has_select = !strips.is_empty();
if (has_select) {
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
float origin[2];
SEQ_image_transform_origin_offset_pixelspace_get(scene, seq, origin);
add_v2_v2(r_pivot, origin);
}
mul_v2_fl(r_pivot, 1.0f / SEQ_collection_len(strips));
mul_v2_fl(r_pivot, 1.0f / strips.size());
}
SEQ_collection_free(strips);
return has_select;
}
@@ -389,11 +386,10 @@ static bool gizmo2d_calc_transform_pivot(const bContext *C, float r_pivot[2])
Editing *ed = SEQ_editing_get(scene);
ListBase *seqbase = SEQ_active_seqbase_get(ed);
ListBase *channels = SEQ_channels_displayed_get(ed);
SeqCollection *strips = SEQ_query_rendered_strips(
blender::VectorSet strips = SEQ_query_rendered_strips(
scene, channels, seqbase, scene->r.cfra, 0);
SEQ_filter_selected_strips(strips);
has_select = SEQ_collection_len(strips) != 0;
SEQ_collection_free(strips);
strips.remove_if([&](Sequence *seq) { return (seq->flag & SELECT) == 0; });
has_select = !strips.is_empty();
}
else if (pivot_point == V3D_AROUND_CENTER_BOUNDS) {
has_select = gizmo2d_calc_bounds(C, r_pivot, nullptr, nullptr);

View File

@@ -42,12 +42,13 @@ struct TransSeqSnapData {
/** \name Snap sources
* \{ */
static int seq_get_snap_source_points_len(SeqCollection *snap_sources)
static int seq_get_snap_source_points_len(blender::Span<Sequence *> snap_sources)
{
return SEQ_collection_len(snap_sources) * 2;
return snap_sources.size() * 2;
}
static void seq_snap_source_points_alloc(TransSeqSnapData *snap_data, SeqCollection *snap_sources)
static void seq_snap_source_points_alloc(TransSeqSnapData *snap_data,
blender::Span<Sequence *> snap_sources)
{
const size_t point_count = seq_get_snap_source_points_len(snap_sources);
snap_data->source_snap_points = static_cast<int *>(
@@ -63,11 +64,10 @@ static int cmp_fn(const void *a, const void *b)
static void seq_snap_source_points_build(const Scene *scene,
TransSeqSnapData *snap_data,
SeqCollection *snap_sources)
blender::Span<Sequence *> snap_sources)
{
int i = 0;
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, snap_sources) {
for (Sequence *seq : snap_sources) {
int left = 0, right = 0;
if (seq->flag & SEQ_LEFTSEL) {
left = right = SEQ_time_left_handle_frame_get(scene, seq);
@@ -99,41 +99,38 @@ static void seq_snap_source_points_build(const Scene *scene,
static void query_strip_effects_fn(const Scene *scene,
Sequence *seq_reference,
ListBase *seqbase,
SeqCollection *collection)
blender::VectorSet<Sequence *> &strips)
{
if (!SEQ_collection_append_strip(seq_reference, collection)) {
if (strips.contains(seq_reference)) {
return; /* Strip is already in set, so all effects connected to it are as well. */
}
strips.add(seq_reference);
/* Find all strips connected to `seq_reference`. */
LISTBASE_FOREACH (Sequence *, seq_test, seqbase) {
if (SEQ_relation_is_effect_of_strip(seq_test, seq_reference)) {
query_strip_effects_fn(scene, seq_test, seqbase, collection);
query_strip_effects_fn(scene, seq_test, seqbase, strips);
}
}
}
static SeqCollection *seq_collection_extract_effects(SeqCollection *collection)
{
SeqCollection *effects = SEQ_collection_create(__func__);
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, collection) {
if (SEQ_effect_get_num_inputs(seq->type) > 0) {
SEQ_collection_append_strip(seq, effects);
}
}
return effects;
}
static SeqCollection *query_snap_targets(Scene *scene,
SeqCollection *snap_sources,
bool exclude_selected)
static blender::VectorSet<Sequence *> query_snap_targets(Scene *scene,
blender::Span<Sequence *> snap_sources,
bool exclude_selected)
{
Editing *ed = SEQ_editing_get(scene);
ListBase *seqbase = SEQ_active_seqbase_get(ed);
ListBase *channels = SEQ_channels_displayed_get(ed);
const short snap_flag = SEQ_tool_settings_snap_flag_get(scene);
SeqCollection *snap_targets = SEQ_collection_create(__func__);
/* Effects will always change position with strip to which they are connected and they don't have
* to be selected. Remove such strips from `snap_targets` collection. */
blender::VectorSet effects_of_snap_sources = snap_sources;
SEQ_iterator_set_expand(scene, seqbase, effects_of_snap_sources, query_strip_effects_fn);
effects_of_snap_sources.remove_if(
[&](Sequence *seq) { return SEQ_effect_get_num_inputs(seq->type) == 0; });
blender::VectorSet<Sequence *> snap_targets;
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
if (exclude_selected && seq->flag & SELECT) {
continue; /* Selected are being transformed. */
@@ -144,21 +141,18 @@ static SeqCollection *query_snap_targets(Scene *scene,
if (seq->type == SEQ_TYPE_SOUND_RAM && (snap_flag & SEQ_SNAP_IGNORE_SOUND)) {
continue;
}
SEQ_collection_append_strip(seq, snap_targets);
}
if (effects_of_snap_sources.contains(seq)) {
continue;
}
/* Effects will always change position with strip to which they are connected and they don't have
* to be selected. Remove such strips from `snap_targets` collection. */
SeqCollection *snap_sources_temp = SEQ_collection_duplicate(snap_sources);
SEQ_collection_expand(scene, seqbase, snap_sources_temp, query_strip_effects_fn);
SeqCollection *snap_sources_effects = seq_collection_extract_effects(snap_sources_temp);
SEQ_collection_exclude(snap_targets, snap_sources_effects);
SEQ_collection_free(snap_sources_temp);
snap_targets.add(seq);
}
return snap_targets;
}
static int seq_get_snap_target_points_count(short snap_mode, SeqCollection *snap_targets)
static int seq_get_snap_target_points_count(short snap_mode,
blender::Span<Sequence *> snap_targets)
{
int count = 2; /* Strip start and end are always used. */
@@ -166,7 +160,7 @@ static int seq_get_snap_target_points_count(short snap_mode, SeqCollection *snap
count += 2;
}
count *= SEQ_collection_len(snap_targets);
count *= snap_targets.size();
if (snap_mode & SEQ_SNAP_TO_CURRENT_FRAME) {
count++;
@@ -177,7 +171,7 @@ static int seq_get_snap_target_points_count(short snap_mode, SeqCollection *snap
static void seq_snap_target_points_alloc(short snap_mode,
TransSeqSnapData *snap_data,
SeqCollection *snap_targets)
blender::Span<Sequence *> snap_targets)
{
const size_t point_count = seq_get_snap_target_points_count(snap_mode, snap_targets);
snap_data->target_snap_points = static_cast<int *>(
@@ -189,7 +183,7 @@ static void seq_snap_target_points_alloc(short snap_mode,
static void seq_snap_target_points_build(Scene *scene,
short snap_mode,
TransSeqSnapData *snap_data,
SeqCollection *snap_targets)
blender::Span<Sequence *> snap_targets)
{
int i = 0;
@@ -198,8 +192,7 @@ static void seq_snap_target_points_build(Scene *scene,
i++;
}
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, snap_targets) {
for (Sequence *seq : snap_targets) {
snap_data->target_snap_points[i] = SEQ_time_left_handle_frame_get(scene, seq);
snap_data->target_snap_points[i + 1] = SEQ_time_right_handle_frame_get(scene, seq);
i += 2;
@@ -258,12 +251,10 @@ TransSeqSnapData *transform_snap_sequencer_data_alloc(const TransInfo *t)
MEM_callocN(sizeof(TransSeqSnapData), __func__));
ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(scene));
SeqCollection *snap_sources = SEQ_query_selected_strips(seqbase);
SeqCollection *snap_targets = query_snap_targets(scene, snap_sources, true);
blender::VectorSet<Sequence *> snap_sources = SEQ_query_selected_strips(seqbase);
blender::VectorSet<Sequence *> snap_targets = query_snap_targets(scene, snap_sources, true);
if (SEQ_collection_len(snap_sources) == 0) {
SEQ_collection_free(snap_targets);
SEQ_collection_free(snap_sources);
if (snap_sources.is_empty()) {
MEM_freeN(snap_data);
return nullptr;
}
@@ -271,12 +262,10 @@ TransSeqSnapData *transform_snap_sequencer_data_alloc(const TransInfo *t)
/* Build arrays of snap points. */
seq_snap_source_points_alloc(snap_data, snap_sources);
seq_snap_source_points_build(scene, snap_data, snap_sources);
SEQ_collection_free(snap_sources);
short snap_mode = t->tsnap.mode;
seq_snap_target_points_alloc(snap_mode, snap_data, snap_targets);
seq_snap_target_points_build(scene, snap_mode, snap_data, snap_targets);
SEQ_collection_free(snap_targets);
return snap_data;
}
@@ -338,9 +327,8 @@ static int transform_snap_sequencer_to_closest_strip_ex(TransInfo *t, int frame_
TransSeqSnapData *snap_data = static_cast<TransSeqSnapData *>(
MEM_callocN(sizeof(TransSeqSnapData), __func__));
SeqCollection *empty_col = SEQ_collection_create(__func__);
SeqCollection *snap_targets = query_snap_targets(scene, empty_col, false);
SEQ_collection_free(empty_col);
blender::VectorSet<Sequence *> empty_col;
blender::VectorSet<Sequence *> snap_targets = query_snap_targets(scene, empty_col, false);
snap_data->source_snap_points = static_cast<int *>(MEM_callocN(sizeof(int) * 2, __func__));
snap_data->source_snap_point_count = 2;
@@ -352,7 +340,6 @@ static int transform_snap_sequencer_to_closest_strip_ex(TransInfo *t, int frame_
/* Build arrays of snap points. */
seq_snap_target_points_alloc(snap_mode, snap_data, snap_targets);
seq_snap_target_points_build(scene, snap_mode, snap_data, snap_targets);
SEQ_collection_free(snap_targets);
t->tsnap.seq_context = snap_data;
bool snap_success = transform_snap_sequencer_calc(t);

View File

@@ -216,32 +216,52 @@ static void rna_Sequence_use_sequence(Main *bmain, Scene *scene, PointerRNA *ptr
DEG_relations_tag_update(bmain);
}
static void add_strips_from_seqbase(const ListBase *seqbase, blender::Vector<Sequence *> &strips)
{
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
strips.append(seq);
if (seq->type == SEQ_TYPE_META) {
add_strips_from_seqbase(&seq->seqbase, strips);
}
}
}
struct SequencesAllIterator {
blender::Vector<Sequence *> strips;
int index;
};
static void rna_SequenceEditor_sequences_all_begin(CollectionPropertyIterator *iter,
PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = SEQ_editing_get(scene);
SeqCollection *all_strips = SEQ_query_all_strips_recursive(&ed->seqbase);
SequencesAllIterator *seq_iter = MEM_new<SequencesAllIterator>(__func__);
seq_iter->index = 0;
add_strips_from_seqbase(&ed->seqbase, seq_iter->strips);
BLI_Iterator *bli_iter = static_cast<BLI_Iterator *>(
MEM_callocN(sizeof(BLI_Iterator), __func__));
bli_iter->data = MEM_callocN(sizeof(SeqIterator), __func__);
iter->internal.custom = bli_iter;
bli_iter->data = seq_iter;
if (!SEQ_iterator_ensure(
all_strips, static_cast<SeqIterator *>(bli_iter->data), (Sequence **)&bli_iter->current))
{
SEQ_collection_free(all_strips);
}
Sequence **seq_arr = seq_iter->strips.begin();
bli_iter->current = *seq_arr;
iter->valid = bli_iter->current != nullptr;
}
static void rna_SequenceEditor_sequences_all_next(CollectionPropertyIterator *iter)
{
BLI_Iterator *bli_iter = static_cast<BLI_Iterator *>(iter->internal.custom);
bli_iter->current = SEQ_iterator_yield(static_cast<SeqIterator *>(bli_iter->data));
iter->valid = bli_iter->current != nullptr;
SequencesAllIterator *seq_iter = static_cast<SequencesAllIterator *>(bli_iter->data);
seq_iter->index++;
Sequence **seq_arr = seq_iter->strips.begin();
bli_iter->current = *(seq_arr + seq_iter->index);
iter->valid = bli_iter->current != nullptr && seq_iter->index < seq_iter->strips.size();
}
static PointerRNA rna_SequenceEditor_sequences_all_get(CollectionPropertyIterator *iter)
@@ -253,11 +273,9 @@ static PointerRNA rna_SequenceEditor_sequences_all_get(CollectionPropertyIterato
static void rna_SequenceEditor_sequences_all_end(CollectionPropertyIterator *iter)
{
BLI_Iterator *bli_iter = static_cast<BLI_Iterator *>(iter->internal.custom);
SeqIterator *seq_iter = static_cast<SeqIterator *>(bli_iter->data);
if (seq_iter->collection != nullptr) {
SEQ_collection_free(seq_iter->collection);
}
MEM_freeN(seq_iter);
SequencesAllIterator *seq_iter = static_cast<SequencesAllIterator *>(bli_iter->data);
MEM_delete(seq_iter);
MEM_freeN(bli_iter);
}
@@ -328,12 +346,12 @@ static void rna_SequenceEditor_retiming_keys_begin(CollectionPropertyIterator *i
static Sequence *strip_by_key_find(Scene *scene, SeqRetimingKey *key)
{
Editing *ed = SEQ_editing_get(scene);
SeqCollection *strips = SEQ_query_all_strips_recursive(&ed->seqbase);
blender::VectorSet strips = SEQ_query_all_strips_recursive(&ed->seqbase);
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
const int retiming_keys_count = SEQ_retiming_keys_count(seq);
SeqRetimingKey *first = seq->retiming_keys;
SeqRetimingKey *last = seq->retiming_keys + SEQ_retiming_keys_count(seq) - 1;
SeqRetimingKey *last = seq->retiming_keys + retiming_keys_count - 1;
if (key >= first && key <= last) {
return seq;
@@ -1499,11 +1517,10 @@ static void rna_Sequence_separate(ID *id, Sequence *seqm, Main *bmain)
/* Find channel owner. If nullptr, owner is `Editing`, otherwise it's `Sequence`. */
static Sequence *rna_SeqTimelineChannel_owner_get(Editing *ed, SeqTimelineChannel *channel)
{
SeqCollection *strips = SEQ_query_all_strips_recursive(&ed->seqbase);
blender::VectorSet strips = SEQ_query_all_strips_recursive(&ed->seqbase);
Sequence *channel_owner = nullptr;
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
if (seq->type != SEQ_TYPE_META) {
continue;
}
@@ -1513,7 +1530,6 @@ static Sequence *rna_SeqTimelineChannel_owner_get(Editing *ed, SeqTimelineChanne
}
}
SEQ_collection_free(strips);
return channel_owner;
}

View File

@@ -9,6 +9,7 @@
*/
#include "BLI_ghash.h"
#include "BLI_vector_set.hh"
struct GSet;
struct GSetIterator;
@@ -85,137 +86,65 @@ typedef bool (*SeqForEachFunc)(struct Sequence *seq, void *user_data);
void SEQ_for_each_callback(struct ListBase *seqbase, SeqForEachFunc callback, void *user_data);
/**
* Create new empty strip collection.
*
* \return empty strip collection.
*/
SeqCollection *SEQ_collection_create(const char *name);
/**
* Duplicate collection
*
* \param collection: collection to be duplicated
* \return duplicate of collection
*/
SeqCollection *SEQ_collection_duplicate(SeqCollection *collection);
/**
* Return number of items in collection.
*/
uint SEQ_collection_len(const SeqCollection *collection);
/**
* Check if seq is in collection.
*/
bool SEQ_collection_has_strip(const struct Sequence *seq, const SeqCollection *collection);
/**
* Add strip to collection.
*
* \param seq: strip to be added
* \param collection: collection to which strip will be added
* \return false if strip is already in set, otherwise true
*/
bool SEQ_collection_append_strip(struct Sequence *seq, SeqCollection *collection);
/**
* Remove strip from collection.
*
* \param seq: strip to be removed
* \param collection: collection from which strip will be removed
* \return true if strip exists in set and it was removed from set, otherwise false
*/
bool SEQ_collection_remove_strip(struct Sequence *seq, SeqCollection *collection);
/**
* Free strip collection.
*
* \param collection: collection to be freed
*/
void SEQ_collection_free(SeqCollection *collection);
/** Quiet compiler warning for free function. */
#define SEQ_collection_free_void_p ((GHashValFreeFP)SEQ_collection_free)
/**
* Move strips from collection_src to collection_dst. Source collection will be freed.
*
* \param collection_dst: destination collection
* \param collection_src: source collection
*/
void SEQ_collection_merge(SeqCollection *collection_dst, SeqCollection *collection_src);
/**
* Remove strips from collection that are also in `exclude_elements`. Source collection will be
* freed.
*
* \param collection: collection from which strips are removed
* \param exclude_elements: collection of strips to be removed
*/
void SEQ_collection_exclude(SeqCollection *collection, SeqCollection *exclude_elements);
/**
* Expand collection by running SEQ_query() for each strip, which will be used as reference.
* Expand set by running `seq_query_func()` for each strip, which will be used as reference.
* Results of these queries will be merged into provided collection.
*
* \param seqbase: ListBase in which strips are queried
* \param collection: SeqCollection to be expanded
* \param strips: set of strips to be expanded
* \param seq_query_func: query function callback
*/
void SEQ_collection_expand(const struct Scene *scene,
struct ListBase *seqbase,
SeqCollection *collection,
void seq_query_func(const struct Scene *scene,
struct Sequence *seq_reference,
struct ListBase *seqbase,
SeqCollection *collection));
void SEQ_iterator_set_expand(const struct Scene *scene,
struct ListBase *seqbase,
blender::VectorSet<Sequence *> &strips,
void seq_query_func(const struct Scene *scene,
struct Sequence *seq_reference,
struct ListBase *seqbase,
blender::VectorSet<Sequence *> &strips));
/**
* Query strips from seqbase. seq_reference is used by query function as filter condition.
*
* \param seq_reference: reference strip for query function
* \param seqbase: ListBase in which strips are queried
* \param seq_query_func: query function callback
* \return strip collection
* \return set of strips
*/
SeqCollection *SEQ_query_by_reference(struct Sequence *seq_reference,
const struct Scene *scene,
struct ListBase *seqbase,
void seq_query_func(const struct Scene *scene,
struct Sequence *seq_reference,
struct ListBase *seqbase,
SeqCollection *collection));
blender::VectorSet<Sequence *> SEQ_query_by_reference(
struct Sequence *seq_reference,
const struct Scene *scene,
struct ListBase *seqbase,
void seq_query_func(const struct Scene *scene,
struct Sequence *seq_reference,
struct ListBase *seqbase,
blender::VectorSet<Sequence *> &strips));
/**
* Query all selected strips in seqbase.
*
* \param seqbase: ListBase in which strips are queried
* \return strip collection
* \return set of strips
*/
SeqCollection *SEQ_query_selected_strips(struct ListBase *seqbase);
blender::VectorSet<Sequence *> SEQ_query_selected_strips(struct ListBase *seqbase);
/**
* Query all unselected strips in seqbase.
*
* \param seqbase: ListBase in which strips are queried
* \return strip collection
* \return set of strips
*/
SeqCollection *SEQ_query_unselected_strips(struct ListBase *seqbase);
blender::VectorSet<Sequence *> SEQ_query_unselected_strips(ListBase *seqbase);
/**
* Query all strips in seqbase. This does not include strips nested in meta strips.
*
* \param seqbase: ListBase in which strips are queried
* \return strip collection
* \return set of strips
*/
SeqCollection *SEQ_query_all_strips(ListBase *seqbase);
blender::VectorSet<Sequence *> SEQ_query_all_strips(ListBase *seqbase);
/**
* Query all strips in seqbase and nested meta strips.
*
* \param seqbase: ListBase in which strips are queried
* \return strip collection
* \return set of strips
*/
SeqCollection *SEQ_query_all_strips_recursive(ListBase *seqbase);
/**
* Query strips that are rendered at \a timeline_frame when \a displayed channel is viewed
*
* \param seqbase: ListBase in which strips are queried
* \param timeline_frame: viewed frame
* \param displayed_channel: viewed channel. when set to 0, no channel filter is applied
* \return strip collection
*/
SeqCollection *SEQ_query_rendered_strips(const struct Scene *scene,
ListBase *channels,
ListBase *seqbase,
int timeline_frame,
int displayed_channel);
blender::VectorSet<Sequence *> SEQ_query_all_strips_recursive(ListBase *seqbase);
/**
* Query all effect strips that are directly or indirectly connected to seq_reference.
* This includes all effects of seq_reference, strips used by another inputs and their effects, so
@@ -223,10 +152,23 @@ SeqCollection *SEQ_query_rendered_strips(const struct Scene *scene,
*
* \param seq_reference: reference strip
* \param seqbase: ListBase in which strips are queried
* \param collection: collection to be filled
* \param strips: set of strips to be filled
*/
void SEQ_query_strip_effect_chain(const struct Scene *scene,
struct Sequence *seq_reference,
struct ListBase *seqbase,
SeqCollection *collection);
void SEQ_filter_selected_strips(SeqCollection *collection);
blender::VectorSet<Sequence *> &strips);
/**
* Query strips that are rendered at \a timeline_frame when \a displayed channel is viewed
*
* \param seqbase: ListBase in which strips are queried
* \param timeline_frame: viewed frame
* \param displayed_channel: viewed channel. when set to 0, no channel filter is applied
* \return set of strips
*/
blender::VectorSet<Sequence *> SEQ_query_rendered_strips(const struct Scene *scene,
ListBase *channels,
ListBase *seqbase,
int timeline_frame,
int displayed_channel);

View File

@@ -10,7 +10,6 @@
struct ListBase;
struct Scene;
struct SeqCollection;
struct Sequence;
bool SEQ_transform_sequence_can_be_translated(Sequence *seq);
@@ -29,18 +28,29 @@ bool SEQ_transform_seqbase_shuffle_ex(ListBase *seqbasep,
Sequence *test,
Scene *evil_scene,
int channel_delta);
bool SEQ_transform_seqbase_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_scene);
bool SEQ_transform_seqbase_shuffle_time(SeqCollection *strips_to_shuffle,
SeqCollection *time_dependent_strips,
ListBase *seqbasep,
Scene *evil_scene,
ListBase *markers,
bool SEQ_transform_seqbase_shuffle(struct ListBase *seqbasep,
struct Sequence *test,
struct Scene *evil_scene);
bool SEQ_transform_seqbase_shuffle_time(blender::Span<Sequence *> strips_to_shuffle,
blender::Span<Sequence *> time_dependent_strips,
struct ListBase *seqbasep,
struct Scene *evil_scene,
struct ListBase *markers,
bool use_sync_markers);
bool SEQ_transform_seqbase_shuffle_time(blender::Span<Sequence *> strips_to_shuffle,
struct ListBase *seqbasep,
struct Scene *evil_scene,
struct ListBase *markers,
bool use_sync_markers);
void SEQ_transform_handle_overlap(Scene *scene,
ListBase *seqbasep,
SeqCollection *transformed_strips,
SeqCollection *time_dependent_strips,
void SEQ_transform_handle_overlap(struct Scene *scene,
struct ListBase *seqbasep,
blender::Span<Sequence *> transformed_strips,
blender::Span<Sequence *> time_dependent_strips,
bool use_sync_markers);
void SEQ_transform_handle_overlap(struct Scene *scene,
struct ListBase *seqbasep,
blender::Span<Sequence *> transformed_strips,
bool use_sync_markers);
/**
* Check if the selected seq's reference unselected seq's.
@@ -116,5 +126,8 @@ void SEQ_image_preview_unit_from_px(const Scene *scene, const float co_src[2], f
* \param r_min: Minimum x and y values
* \param r_max: Maximum x and y values
*/
void SEQ_image_transform_bounding_box_from_collection(
Scene *scene, SeqCollection *strips, bool apply_rotation, float r_min[2], float r_max[2]);
void SEQ_image_transform_bounding_box_from_collection(struct Scene *scene,
blender::Span<Sequence *> strips,
bool apply_rotation,
float r_min[2],
float r_max[2]);

View File

@@ -17,6 +17,7 @@
#include "BLI_ghash.h"
#include "BLI_listbase.h"
#include "BLI_set.hh"
#include "BKE_scene.h"
@@ -26,37 +27,7 @@
#include "SEQ_time.hh"
#include "render.hh"
/* -------------------------------------------------------------------- */
/** \name Iterator API
* \{ */
bool SEQ_iterator_ensure(SeqCollection *collection, SeqIterator *iterator, Sequence **r_seq)
{
if (iterator->iterator_initialized) {
return true;
}
if (BLI_gset_len(collection->set) == 0) {
return false;
}
iterator->collection = collection;
BLI_gsetIterator_init(&iterator->gsi, iterator->collection->set);
iterator->iterator_initialized = true;
*r_seq = static_cast<Sequence *>(BLI_gsetIterator_getKey(&iterator->gsi));
BLI_gsetIterator_step(&iterator->gsi);
return true;
}
Sequence *SEQ_iterator_yield(SeqIterator *iterator)
{
Sequence *seq = static_cast<Sequence *>(
BLI_gsetIterator_done(&iterator->gsi) ? nullptr : BLI_gsetIterator_getKey(&iterator->gsi));
BLI_gsetIterator_step(&iterator->gsi);
return seq;
}
using blender::VectorSet;
static bool seq_for_each_recursive(ListBase *seqbase, SeqForEachFunc callback, void *user_data)
{
@@ -79,194 +50,116 @@ void SEQ_for_each_callback(ListBase *seqbase, SeqForEachFunc callback, void *use
seq_for_each_recursive(seqbase, callback, user_data);
}
void SEQ_collection_free(SeqCollection *collection)
VectorSet<Sequence *> SEQ_query_by_reference(Sequence *reference_strip,
const Scene *scene,
ListBase *seqbase,
void seq_query_func(const Scene *scene,
Sequence *seq_reference,
ListBase *seqbase,
VectorSet<Sequence *> &strips))
{
BLI_gset_free(collection->set, nullptr);
MEM_freeN(collection);
VectorSet<Sequence *> strips;
seq_query_func(scene, reference_strip, seqbase, strips);
return strips;
}
SeqCollection *SEQ_collection_create(const char *name)
void SEQ_iterator_set_expand(const Scene *scene,
ListBase *seqbase,
VectorSet<Sequence *> &strips,
void seq_query_func(const Scene *scene,
Sequence *seq_reference,
ListBase *seqbase,
VectorSet<Sequence *> &strips))
{
SeqCollection *collection = static_cast<SeqCollection *>(
MEM_callocN(sizeof(SeqCollection), name));
collection->set = BLI_gset_new(
BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "SeqCollection GSet");
return collection;
}
/* Collect expanded results for each sequence in provided VectorSet. */
VectorSet<Sequence *> query_matches;
uint SEQ_collection_len(const SeqCollection *collection)
{
return BLI_gset_len(collection->set);
}
bool SEQ_collection_has_strip(const Sequence *seq, const SeqCollection *collection)
{
return BLI_gset_haskey(collection->set, seq);
}
SeqCollection *SEQ_query_by_reference(Sequence *seq_reference,
const Scene *scene,
ListBase *seqbase,
void seq_query_func(const Scene *scene,
Sequence *seq_reference,
ListBase *seqbase,
SeqCollection *collection))
{
SeqCollection *collection = SEQ_collection_create(__func__);
seq_query_func(scene, seq_reference, seqbase, collection);
return collection;
}
bool SEQ_collection_append_strip(Sequence *seq, SeqCollection *collection)
{
void **key;
if (BLI_gset_ensure_p_ex(collection->set, seq, &key)) {
return false;
for (Sequence *strip : strips) {
query_matches.add_multiple(SEQ_query_by_reference(strip, scene, seqbase, seq_query_func));
}
*key = (void *)seq;
return true;
/* Merge all expanded results in provided VectorSet. */
query_matches.add_multiple(query_matches);
}
bool SEQ_collection_remove_strip(Sequence *seq, SeqCollection *collection)
{
return BLI_gset_remove(collection->set, seq, nullptr);
}
void SEQ_collection_merge(SeqCollection *collection_dst, SeqCollection *collection_src)
{
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, collection_src) {
SEQ_collection_append_strip(seq, collection_dst);
}
SEQ_collection_free(collection_src);
}
void SEQ_collection_exclude(SeqCollection *collection, SeqCollection *exclude_elements)
{
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, exclude_elements) {
SEQ_collection_remove_strip(seq, collection);
}
SEQ_collection_free(exclude_elements);
}
void SEQ_collection_expand(const Scene *scene,
ListBase *seqbase,
SeqCollection *collection,
void seq_query_func(const Scene *scene,
Sequence *seq_reference,
ListBase *seqbase,
SeqCollection *collection))
{
/* Collect expanded results for each sequence in provided SeqIteratorCollection. */
SeqCollection *query_matches = SEQ_collection_create(__func__);
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, collection) {
SEQ_collection_merge(query_matches,
SEQ_query_by_reference(seq, scene, seqbase, seq_query_func));
}
/* Merge all expanded results in provided SeqIteratorCollection. */
SEQ_collection_merge(collection, query_matches);
}
SeqCollection *SEQ_collection_duplicate(SeqCollection *collection)
{
SeqCollection *duplicate = SEQ_collection_create(__func__);
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, collection) {
SEQ_collection_append_strip(seq, duplicate);
}
return duplicate;
}
/** \} */
static void query_all_strips_recursive(ListBase *seqbase, SeqCollection *collection)
static void query_all_strips_recursive(ListBase *seqbase, VectorSet<Sequence *> &strips)
{
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
if (seq->type == SEQ_TYPE_META) {
query_all_strips_recursive(&seq->seqbase, collection);
query_all_strips_recursive(&seq->seqbase, strips);
}
SEQ_collection_append_strip(seq, collection);
strips.add(seq);
}
}
SeqCollection *SEQ_query_all_strips_recursive(ListBase *seqbase)
VectorSet<Sequence *> SEQ_query_all_strips_recursive(ListBase *seqbase)
{
SeqCollection *collection = SEQ_collection_create(__func__);
static VectorSet<Sequence *> strips;
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
if (seq->type == SEQ_TYPE_META) {
query_all_strips_recursive(&seq->seqbase, collection);
query_all_strips_recursive(&seq->seqbase, strips);
}
SEQ_collection_append_strip(seq, collection);
strips.add(seq);
}
return collection;
return strips;
}
SeqCollection *SEQ_query_all_strips(ListBase *seqbase)
VectorSet<Sequence *> SEQ_query_all_strips(ListBase *seqbase)
{
SeqCollection *collection = SEQ_collection_create(__func__);
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
SEQ_collection_append_strip(seq, collection);
static VectorSet<Sequence *> strips;
LISTBASE_FOREACH (Sequence *, strip, seqbase) {
strips.add(strip);
}
return collection;
return strips;
}
SeqCollection *SEQ_query_selected_strips(ListBase *seqbase)
VectorSet<Sequence *> SEQ_query_selected_strips(ListBase *seqbase)
{
SeqCollection *collection = SEQ_collection_create(__func__);
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
if ((seq->flag & SELECT) == 0) {
continue;
VectorSet<Sequence *> strips;
LISTBASE_FOREACH (Sequence *, strip, seqbase) {
if ((strip->flag & SELECT) != 0) {
strips.add(strip);
}
SEQ_collection_append_strip(seq, collection);
}
return collection;
return strips;
}
static SeqCollection *query_strips_at_frame(const Scene *scene,
ListBase *seqbase,
const int timeline_frame)
static VectorSet<Sequence *> query_strips_at_frame(const Scene *scene,
ListBase *seqbase,
const int timeline_frame)
{
SeqCollection *collection = SEQ_collection_create(__func__);
VectorSet<Sequence *> strips;
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
if (SEQ_time_strip_intersects_frame(scene, seq, timeline_frame)) {
SEQ_collection_append_strip(seq, collection);
LISTBASE_FOREACH (Sequence *, strip, seqbase) {
if (SEQ_time_strip_intersects_frame(scene, strip, timeline_frame)) {
strips.add(strip);
}
}
return collection;
return strips;
}
static void collection_filter_channel_up_to_incl(SeqCollection *collection, const int channel)
static void collection_filter_channel_up_to_incl(VectorSet<Sequence *> &strips, const int channel)
{
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, collection) {
if (seq->machine <= channel) {
continue;
}
SEQ_collection_remove_strip(seq, collection);
}
strips.remove_if([&](Sequence *strip) { return strip->machine > channel; });
}
/* Check if seq must be rendered. This depends on whole stack in some cases, not only seq itself.
* Order of applying these conditions is important. */
static bool must_render_strip(const Sequence *seq, SeqCollection *strips_at_timeline_frame)
static bool must_render_strip(VectorSet<Sequence *> &strips, Sequence *strip)
{
bool seq_have_effect_in_stack = false;
Sequence *seq_iter;
SEQ_ITERATOR_FOREACH (seq_iter, strips_at_timeline_frame) {
for (Sequence *strip_iter : strips) {
/* Strips is below another strip with replace blending are not rendered. */
if (seq_iter->blend_mode == SEQ_BLEND_REPLACE && seq->machine < seq_iter->machine) {
if (strip_iter->blend_mode == SEQ_BLEND_REPLACE && strip->machine < strip_iter->machine) {
return false;
}
if ((seq_iter->type & SEQ_TYPE_EFFECT) != 0 && SEQ_relation_is_effect_of_strip(seq_iter, seq))
if ((strip_iter->type & SEQ_TYPE_EFFECT) != 0 &&
SEQ_relation_is_effect_of_strip(strip_iter, strip))
{
/* Strips in same channel or higher than its effect are rendered. */
if (seq->machine >= seq_iter->machine) {
if (strip->machine >= strip_iter->machine) {
return true;
}
/* Mark that this strip has effect in stack, that is above the strip. */
@@ -275,7 +168,7 @@ static bool must_render_strip(const Sequence *seq, SeqCollection *strips_at_time
}
/* All effects are rendered (with respect to conditions above). */
if ((seq->type & SEQ_TYPE_EFFECT) != 0) {
if ((strip->type & SEQ_TYPE_EFFECT) != 0) {
return true;
}
@@ -287,91 +180,74 @@ static bool must_render_strip(const Sequence *seq, SeqCollection *strips_at_time
return true;
}
/* Remove strips we don't want to render from collection. */
static void collection_filter_rendered_strips(ListBase *channels, SeqCollection *collection)
/* Remove strips we don't want to render from VectorSet. */
static void collection_filter_rendered_strips(VectorSet<Sequence *> &strips, ListBase *channels)
{
Sequence *seq;
/* Remove sound strips and muted strips from collection, because these are not rendered.
/* Remove sound strips and muted strips from VectorSet, because these are not rendered.
* Function #must_render_strip() don't have to check for these strips anymore. */
SEQ_ITERATOR_FOREACH (seq, collection) {
if (seq->type == SEQ_TYPE_SOUND_RAM || SEQ_render_is_muted(channels, seq)) {
SEQ_collection_remove_strip(seq, collection);
}
}
strips.remove_if([&](Sequence *strip) {
return strip->type == SEQ_TYPE_SOUND_RAM || SEQ_render_is_muted(channels, strip);
});
SEQ_ITERATOR_FOREACH (seq, collection) {
if (must_render_strip(seq, collection)) {
continue;
}
SEQ_collection_remove_strip(seq, collection);
}
strips.remove_if([&](Sequence *strip) { return !must_render_strip(strips, strip); });
}
SeqCollection *SEQ_query_rendered_strips(const Scene *scene,
ListBase *channels,
ListBase *seqbase,
const int timeline_frame,
const int displayed_channel)
VectorSet<Sequence *> SEQ_query_rendered_strips(const Scene *scene,
ListBase *channels,
ListBase *seqbase,
const int timeline_frame,
const int displayed_channel)
{
SeqCollection *collection = query_strips_at_frame(scene, seqbase, timeline_frame);
VectorSet strips = query_strips_at_frame(scene, seqbase, timeline_frame);
if (displayed_channel != 0) {
collection_filter_channel_up_to_incl(collection, displayed_channel);
collection_filter_channel_up_to_incl(strips, displayed_channel);
}
collection_filter_rendered_strips(channels, collection);
return collection;
collection_filter_rendered_strips(strips, channels);
return strips;
}
SeqCollection *SEQ_query_unselected_strips(ListBase *seqbase)
VectorSet<Sequence *> SEQ_query_unselected_strips(ListBase *seqbase)
{
SeqCollection *collection = SEQ_collection_create(__func__);
VectorSet<Sequence *> strips;
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
if ((seq->flag & SELECT) != 0) {
continue;
}
SEQ_collection_append_strip(seq, collection);
strips.add(seq);
}
return collection;
return strips;
}
void SEQ_query_strip_effect_chain(const Scene *scene,
Sequence *seq_reference,
Sequence *reference_strip,
ListBase *seqbase,
SeqCollection *collection)
VectorSet<Sequence *> &strips)
{
if (!SEQ_collection_append_strip(seq_reference, collection)) {
if (strips.contains(reference_strip)) {
return; /* Strip is already in set, so all effects connected to it are as well. */
}
/* Find all strips that seq_reference is connected to. */
if (seq_reference->type & SEQ_TYPE_EFFECT) {
if (seq_reference->seq1) {
SEQ_query_strip_effect_chain(scene, seq_reference->seq1, seqbase, collection);
strips.add(reference_strip);
/* Find all strips that reference_strip is connected to. */
if (reference_strip->type & SEQ_TYPE_EFFECT) {
if (reference_strip->seq1) {
SEQ_query_strip_effect_chain(scene, reference_strip->seq1, seqbase, strips);
}
if (seq_reference->seq2) {
SEQ_query_strip_effect_chain(scene, seq_reference->seq2, seqbase, collection);
if (reference_strip->seq2) {
SEQ_query_strip_effect_chain(scene, reference_strip->seq2, seqbase, strips);
}
if (seq_reference->seq3) {
SEQ_query_strip_effect_chain(scene, seq_reference->seq3, seqbase, collection);
if (reference_strip->seq3) {
SEQ_query_strip_effect_chain(scene, reference_strip->seq3, seqbase, strips);
}
}
/* Find all strips connected to seq_reference. */
/* Find all strips connected to reference_strip. */
LISTBASE_FOREACH (Sequence *, seq_test, seqbase) {
if (seq_test->seq1 == seq_reference || seq_test->seq2 == seq_reference ||
seq_test->seq3 == seq_reference)
if (seq_test->seq1 == reference_strip || seq_test->seq2 == reference_strip ||
seq_test->seq3 == reference_strip)
{
SEQ_query_strip_effect_chain(scene, seq_test, seqbase, collection);
}
}
}
void SEQ_filter_selected_strips(SeqCollection *collection)
{
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, collection) {
if ((seq->flag & SELECT) == 0) {
SEQ_collection_remove_strip(seq, collection);
SEQ_query_strip_effect_chain(scene, seq_test, seqbase, strips);
}
}
}

View File

@@ -397,7 +397,7 @@ static bool seq_prefetch_seq_has_disk_cache(PrefetchJob *pfjob,
static bool seq_prefetch_scene_strip_is_rendered(PrefetchJob *pfjob,
ListBase *channels,
ListBase *seqbase,
SeqCollection *scene_strips,
blender::Span<Sequence *> scene_strips,
bool is_recursive_check)
{
float cfra = seq_prefetch_cfra(pfjob);
@@ -421,8 +421,7 @@ static bool seq_prefetch_scene_strip_is_rendered(PrefetchJob *pfjob,
}
/* Check if strip is effect of scene strip or uses it as modifier. This is recursive check. */
Sequence *seq_scene;
SEQ_ITERATOR_FOREACH (seq_scene, scene_strips) {
for (Sequence *seq_scene : scene_strips) {
if (SEQ_relations_render_loop_check(seq, seq_scene)) {
return true;
}
@@ -431,27 +430,25 @@ static bool seq_prefetch_scene_strip_is_rendered(PrefetchJob *pfjob,
return false;
}
static SeqCollection *query_scene_strips(ListBase *seqbase)
static blender::VectorSet<Sequence *> query_scene_strips(ListBase *seqbase)
{
SeqCollection *collection = SEQ_query_all_strips_recursive(seqbase);
blender::VectorSet<Sequence *> strips;
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
if (seq->type != SEQ_TYPE_SCENE || (seq->flag & SEQ_SCENE_STRIPS) != 0) {
SEQ_collection_remove_strip(seq, collection);
strips.add(seq);
}
}
return collection;
return strips;
}
/* Prefetch must avoid rendering scene strips, because rendering in background locks UI and can
* make it unresponsive for long time periods. */
static bool seq_prefetch_must_skip_frame(PrefetchJob *pfjob, ListBase *channels, ListBase *seqbase)
{
SeqCollection *scene_strips = query_scene_strips(seqbase);
blender::VectorSet<Sequence *> scene_strips = query_scene_strips(seqbase);
if (seq_prefetch_scene_strip_is_rendered(pfjob, channels, seqbase, scene_strips, false)) {
SEQ_collection_free(scene_strips);
return true;
}
SEQ_collection_free(scene_strips);
return false;
}

View File

@@ -279,25 +279,22 @@ int seq_get_shown_sequences(const Scene *scene,
const int chanshown,
Sequence **r_seq_arr)
{
SeqCollection *collection = SEQ_query_rendered_strips(
blender::VectorSet strips = SEQ_query_rendered_strips(
scene, channels, seqbase, timeline_frame, chanshown);
const int strip_count = BLI_gset_len(collection->set);
const int strip_count = strips.size();
if (UNLIKELY(strip_count > MAXSEQ)) {
SEQ_collection_free(collection);
BLI_assert_msg(0, "Too many strips, this shouldn't happen");
return 0;
}
/* Copy collection elements into array. */
memset(r_seq_arr, 0, sizeof(Sequence *) * (MAXSEQ + 1));
Sequence *seq;
int index = 0;
SEQ_ITERATOR_FOREACH (seq, collection) {
for (Sequence *seq : strips) {
r_seq_arr[index] = seq;
index++;
}
SEQ_collection_free(collection);
/* Sort array by channel. */
qsort(r_seq_arr, strip_count, sizeof(Sequence *), seq_channel_cmp_fn);

View File

@@ -17,9 +17,12 @@
#include "BLI_ghash.h"
#include "BLI_listbase.h"
#include "BLI_map.hh"
#include "BLI_string.h"
#include "BLI_sys_types.h"
#include "BLI_threads.h"
#include "BLI_vector_set.hh"
#include <cstring>
#include "MEM_guardedalloc.h"
@@ -29,7 +32,7 @@ static ThreadMutex lookup_lock = BLI_MUTEX_INITIALIZER;
struct SequenceLookup {
GHash *seq_by_name;
GHash *meta_by_seq;
GHash *effects_by_seq;
blender::Map<const Sequence *, blender::VectorSet<Sequence *>> effects_by_seq;
eSequenceLookupTag tag;
};
@@ -37,11 +40,10 @@ static void seq_sequence_lookup_init(SequenceLookup *lookup)
{
lookup->seq_by_name = BLI_ghash_str_new(__func__);
lookup->meta_by_seq = BLI_ghash_ptr_new(__func__);
lookup->effects_by_seq = BLI_ghash_ptr_new(__func__);
lookup->tag |= SEQ_LOOKUP_TAG_INVALID;
}
static void seq_sequence_lookup_append_effect(Sequence *input,
static void seq_sequence_lookup_append_effect(const Sequence *input,
Sequence *effect,
SequenceLookup *lookup)
{
@@ -49,14 +51,9 @@ static void seq_sequence_lookup_append_effect(Sequence *input,
return;
}
SeqCollection *effects = static_cast<SeqCollection *>(
BLI_ghash_lookup(lookup->effects_by_seq, input));
if (effects == nullptr) {
effects = SEQ_collection_create(__func__);
BLI_ghash_insert(lookup->effects_by_seq, input, effects);
}
blender::VectorSet<Sequence *> &effects = lookup->effects_by_seq.lookup_or_add_default(input);
SEQ_collection_append_strip(effect, effects);
effects.add(effect);
}
static void seq_sequence_lookup_build_effect(Sequence *seq, SequenceLookup *lookup)
@@ -93,8 +90,7 @@ static void seq_sequence_lookup_build(const Scene *scene, SequenceLookup *lookup
static SequenceLookup *seq_sequence_lookup_new()
{
SequenceLookup *lookup = static_cast<SequenceLookup *>(
MEM_callocN(sizeof(SequenceLookup), __func__));
SequenceLookup *lookup = MEM_new<SequenceLookup>(__func__);
seq_sequence_lookup_init(lookup);
return lookup;
}
@@ -107,11 +103,9 @@ static void seq_sequence_lookup_free(SequenceLookup **lookup)
BLI_ghash_free((*lookup)->seq_by_name, nullptr, nullptr);
BLI_ghash_free((*lookup)->meta_by_seq, nullptr, nullptr);
BLI_ghash_free((*lookup)->effects_by_seq, nullptr, SEQ_collection_free_void_p);
(*lookup)->seq_by_name = nullptr;
(*lookup)->meta_by_seq = nullptr;
(*lookup)->effects_by_seq = nullptr;
MEM_freeN(*lookup);
MEM_delete(*lookup);
*lookup = nullptr;
}
@@ -170,16 +164,16 @@ Sequence *seq_sequence_lookup_meta_by_seq(const Scene *scene, const Sequence *ke
return seq;
}
SeqCollection *seq_sequence_lookup_effects_by_seq(const Scene *scene, const Sequence *key)
blender::Span<Sequence *> seq_sequence_lookup_effects_by_seq(const Scene *scene,
const Sequence *key)
{
BLI_assert(scene->ed);
BLI_mutex_lock(&lookup_lock);
seq_sequence_lookup_update_if_needed(scene, &scene->ed->runtime.sequence_lookup);
SequenceLookup *lookup = scene->ed->runtime.sequence_lookup;
SeqCollection *effects = static_cast<SeqCollection *>(
BLI_ghash_lookup(lookup->effects_by_seq, key));
blender::VectorSet<Sequence *> &effects = lookup->effects_by_seq.lookup_or_add_default(key);
BLI_mutex_unlock(&lookup_lock);
return effects;
return effects.as_span();
}
void SEQ_sequence_lookup_tag(const Scene *scene, eSequenceLookupTag tag)

View File

@@ -4,18 +4,15 @@
#pragma once
#include <BLI_vector_set.hh>
/** \file
* \ingroup sequencer
*/
#ifdef __cplusplus
extern "C" {
#endif
struct Scene;
struct Sequence;
struct StripProxy;
struct SeqCollection;
/**
* Cache must be freed before calling this function
* since it leaves the seqbase in an invalid state.
@@ -44,8 +41,5 @@ struct Sequence *seq_sequence_lookup_meta_by_seq(const struct Scene *scene,
*
* \return collection of effect strips
*/
struct SeqCollection *seq_sequence_lookup_effects_by_seq(const struct Scene *scene,
const struct Sequence *key);
#ifdef __cplusplus
}
#endif
blender::Span<Sequence *> seq_sequence_lookup_effects_by_seq(const struct Scene *scene,
const struct Sequence *key);

View File

@@ -511,8 +511,6 @@ Sequence *SEQ_add_movie_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqL
seq_add_set_name(scene, seq, load_data);
seq_add_generic_update(scene, seq);
/* Prevent high memory usage when adding many files at once. */
SEQ_relations_sequence_free_anim(seq);
MEM_freeN(anim_arr);
return seq;
}
@@ -628,9 +626,6 @@ void SEQ_add_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, const boo
if (seq->len < 0) {
seq->len = 0;
}
/* Prevent high memory usage when reloading many files at once. */
SEQ_relations_sequence_free_anim(seq);
break;
}
case SEQ_TYPE_MOVIECLIP:

View File

@@ -244,18 +244,15 @@ bool SEQ_edit_move_strip_to_meta(Scene *scene,
return false;
}
SeqCollection *collection = SEQ_collection_create(__func__);
SEQ_collection_append_strip(src_seq, collection);
SEQ_collection_expand(scene, seqbase, collection, SEQ_query_strip_effect_chain);
blender::VectorSet<Sequence *> strips;
strips.add(src_seq);
SEQ_iterator_set_expand(scene, seqbase, strips, SEQ_query_strip_effect_chain);
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, collection) {
for (Sequence *seq : strips) {
/* Move to meta. */
SEQ_edit_move_strip_to_seqbase(scene, seqbase, seq, &dst_seqm->seqbase);
}
SEQ_collection_free(collection);
return true;
}
@@ -383,12 +380,11 @@ static bool seq_edit_split_effect_inputs_intersect(const Scene *scene,
}
static bool seq_edit_split_operation_permitted_check(const Scene *scene,
SeqCollection *strips,
blender::Span<Sequence *> strips,
const int timeline_frame,
const char **r_error)
{
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
ListBase *channels = SEQ_channels_displayed_get(SEQ_editing_get(scene));
if (SEQ_transform_is_locked(channels, seq)) {
*r_error = "Strip is locked.";
@@ -428,12 +424,11 @@ Sequence *SEQ_edit_strip_split(Main *bmain,
}
/* Whole strip chain must be duplicated in order to preserve relationships. */
SeqCollection *collection = SEQ_collection_create(__func__);
SEQ_collection_append_strip(seq, collection);
SEQ_collection_expand(scene, seqbase, collection, SEQ_query_strip_effect_chain);
blender::VectorSet<Sequence *> strips;
strips.add(seq);
SEQ_iterator_set_expand(scene, seqbase, strips, SEQ_query_strip_effect_chain);
if (!seq_edit_split_operation_permitted_check(scene, collection, timeline_frame, r_error)) {
SEQ_collection_free(collection);
if (!seq_edit_split_operation_permitted_check(scene, strips, timeline_frame, r_error)) {
return nullptr;
}
@@ -442,7 +437,7 @@ Sequence *SEQ_edit_strip_split(Main *bmain,
SEQ_animation_backup_original(scene, &animation_backup);
ListBase left_strips = {nullptr, nullptr};
SEQ_ITERATOR_FOREACH (seq, collection) {
for (Sequence *seq : strips) {
/* Move strips in collection from seqbase to new ListBase. */
BLI_remlink(seqbase, seq);
BLI_addtail(&left_strips, seq);
@@ -451,8 +446,6 @@ Sequence *SEQ_edit_strip_split(Main *bmain,
SEQ_animation_duplicate_backup_to_scene(scene, seq, &animation_backup);
}
SEQ_collection_free(collection);
/* Duplicate ListBase. */
ListBase right_strips = {nullptr, nullptr};
SEQ_sequence_base_dupli_recursive(scene, scene, &right_strips, &left_strips, SEQ_DUPE_ALL, 0);

View File

@@ -978,7 +978,8 @@ void SEQ_retiming_key_timeline_frame_set(const Scene *scene,
}
SEQ_time_update_meta_strip_range(scene, seq_sequence_lookup_meta_by_seq(scene, seq));
seq_time_update_effects_strip_range(scene, seq_sequence_lookup_effects_by_seq(scene, seq));
blender::Span effects = seq_sequence_lookup_effects_by_seq(scene, seq);
seq_time_update_effects_strip_range(scene, effects);
}
void SEQ_retiming_key_speed_set(const Scene *scene,

View File

@@ -201,7 +201,8 @@ void SEQ_time_update_meta_strip_range(const Scene *scene, Sequence *seq_meta)
seq_update_sound_bounds_recursive(scene, seq_meta);
SEQ_time_update_meta_strip_range(scene, seq_sequence_lookup_meta_by_seq(scene, seq_meta));
seq_time_update_effects_strip_range(scene, seq_sequence_lookup_effects_by_seq(scene, seq_meta));
blender::Span effects = seq_sequence_lookup_effects_by_seq(scene, seq_meta);
seq_time_update_effects_strip_range(scene, effects);
}
void seq_time_effect_range_set(const Scene *scene, Sequence *seq)
@@ -235,22 +236,18 @@ void seq_time_effect_range_set(const Scene *scene, Sequence *seq)
seq->len = seq->enddisp - seq->startdisp;
}
void seq_time_update_effects_strip_range(const Scene *scene, SeqCollection *effects)
void seq_time_update_effects_strip_range(const Scene *scene, blender::Span<Sequence *> &effects)
{
if (effects == nullptr) {
return;
}
Sequence *seq;
/* First pass: Update length of immediate effects. */
SEQ_ITERATOR_FOREACH (seq, effects) {
for (Sequence *seq : effects) {
seq_time_effect_range_set(scene, seq);
}
/* Second pass: Recursive call to update effects in chain and in order, so they inherit length
* correctly. */
SEQ_ITERATOR_FOREACH (seq, effects) {
seq_time_update_effects_strip_range(scene, seq_sequence_lookup_effects_by_seq(scene, seq));
for (Sequence *seq : effects) {
blender::Span effects = seq_sequence_lookup_effects_by_seq(scene, seq);
seq_time_update_effects_strip_range(scene, effects);
}
}
@@ -398,11 +395,10 @@ void SEQ_timeline_boundbox(const Scene *scene, const ListBase *seqbase, rctf *re
}
static bool strip_exists_at_frame(const Scene *scene,
SeqCollection *all_strips,
blender::Span<Sequence *> strips,
const int timeline_frame)
{
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, all_strips) {
for (Sequence *seq : strips) {
if (SEQ_time_strip_intersects_frame(scene, seq, timeline_frame)) {
return true;
}
@@ -423,12 +419,12 @@ void seq_time_gap_info_get(const Scene *scene,
int timeline_frame = initial_frame;
r_gap_info->gap_exists = false;
SeqCollection *collection = SEQ_query_all_strips(seqbase);
blender::VectorSet strips = SEQ_query_all_strips(seqbase);
if (!strip_exists_at_frame(scene, collection, initial_frame)) {
if (!strip_exists_at_frame(scene, strips, initial_frame)) {
/* Search backward for gap_start_frame. */
for (; timeline_frame >= sfra; timeline_frame--) {
if (strip_exists_at_frame(scene, collection, timeline_frame)) {
if (strip_exists_at_frame(scene, strips, timeline_frame)) {
break;
}
}
@@ -438,7 +434,7 @@ void seq_time_gap_info_get(const Scene *scene,
else {
/* Search forward for gap_start_frame. */
for (; timeline_frame <= efra; timeline_frame++) {
if (!strip_exists_at_frame(scene, collection, timeline_frame)) {
if (!strip_exists_at_frame(scene, strips, timeline_frame)) {
r_gap_info->gap_start_frame = timeline_frame;
break;
}
@@ -446,7 +442,7 @@ void seq_time_gap_info_get(const Scene *scene,
}
/* Search forward for gap_end_frame. */
for (; timeline_frame <= efra; timeline_frame++) {
if (strip_exists_at_frame(scene, collection, timeline_frame)) {
if (strip_exists_at_frame(scene, strips, timeline_frame)) {
const int gap_end_frame = timeline_frame;
r_gap_info->gap_length = gap_end_frame - r_gap_info->gap_start_frame;
r_gap_info->gap_exists = true;
@@ -499,7 +495,8 @@ void SEQ_time_start_frame_set(const Scene *scene, Sequence *seq, int timeline_fr
{
seq->start = timeline_frame;
SEQ_time_update_meta_strip_range(scene, seq_sequence_lookup_meta_by_seq(scene, seq));
seq_time_update_effects_strip_range(scene, seq_sequence_lookup_effects_by_seq(scene, seq));
blender::Span effects = seq_sequence_lookup_effects_by_seq(scene, seq);
seq_time_update_effects_strip_range(scene, effects);
}
float SEQ_time_content_end_frame_get(const Scene *scene, const Sequence *seq)
@@ -548,7 +545,8 @@ void SEQ_time_left_handle_frame_set(const Scene *scene, Sequence *seq, int timel
seq->startdisp = timeline_frame; /* Only to make files usable in older versions. */
SEQ_time_update_meta_strip_range(scene, seq_sequence_lookup_meta_by_seq(scene, seq));
seq_time_update_effects_strip_range(scene, seq_sequence_lookup_effects_by_seq(scene, seq));
blender::Span effects = seq_sequence_lookup_effects_by_seq(scene, seq);
seq_time_update_effects_strip_range(scene, effects);
}
void SEQ_time_right_handle_frame_set(const Scene *scene, Sequence *seq, int timeline_frame)
@@ -563,7 +561,8 @@ void SEQ_time_right_handle_frame_set(const Scene *scene, Sequence *seq, int time
seq->enddisp = timeline_frame; /* Only to make files usable in older versions. */
SEQ_time_update_meta_strip_range(scene, seq_sequence_lookup_meta_by_seq(scene, seq));
seq_time_update_effects_strip_range(scene, seq_sequence_lookup_effects_by_seq(scene, seq));
blender::Span effects = seq_sequence_lookup_effects_by_seq(scene, seq);
seq_time_update_effects_strip_range(scene, effects);
}
void seq_time_translate_handles(const Scene *scene, Sequence *seq, const int offset)
@@ -574,5 +573,6 @@ void seq_time_translate_handles(const Scene *scene, Sequence *seq, const int off
seq->enddisp -= offset; /* Only to make files usable in older versions. */
SEQ_time_update_meta_strip_range(scene, seq_sequence_lookup_meta_by_seq(scene, seq));
seq_time_update_effects_strip_range(scene, seq_sequence_lookup_effects_by_seq(scene, seq));
blender::Span effects = seq_sequence_lookup_effects_by_seq(scene, seq);
seq_time_update_effects_strip_range(scene, effects);
}

View File

@@ -4,6 +4,8 @@
#pragma once
#include <BLI_span.hh>
/** \file
* \ingroup sequencer
*/
@@ -38,7 +40,8 @@ void seq_time_effect_range_set(const struct Scene *scene, Sequence *seq);
/**
* Update strip `startdisp` and `enddisp` (n-input effects have no length to calculate these).
*/
void seq_time_update_effects_strip_range(const struct Scene *scene, struct SeqCollection *effects);
void seq_time_update_effects_strip_range(const struct Scene *scene,
blender::Span<Sequence *> &effects);
void seq_time_translate_handles(const struct Scene *scene, struct Sequence *seq, const int offset);
float seq_time_media_playback_rate_factor_get(const struct Scene *scene,
const struct Sequence *seq);

View File

@@ -142,8 +142,8 @@ void SEQ_transform_translate_sequence(Scene *evil_scene, Sequence *seq, int delt
SEQ_offset_animdata(evil_scene, seq, delta);
SEQ_time_update_meta_strip_range(evil_scene, seq_sequence_lookup_meta_by_seq(evil_scene, seq));
seq_time_update_effects_strip_range(evil_scene,
seq_sequence_lookup_effects_by_seq(evil_scene, seq));
blender::Span effects = seq_sequence_lookup_effects_by_seq(evil_scene, seq);
seq_time_update_effects_strip_range(evil_scene, effects);
}
bool SEQ_transform_seqbase_shuffle_ex(ListBase *seqbasep,
@@ -203,17 +203,16 @@ static bool shuffle_seq_test_overlap(const Scene *scene,
}
static int shuffle_seq_time_offset_get(const Scene *scene,
SeqCollection *strips_to_shuffle,
blender::Span<Sequence *> strips_to_shuffle,
ListBase *seqbasep,
char dir)
{
int offset = 0;
Sequence *seq;
bool all_conflicts_resolved = false;
while (!all_conflicts_resolved) {
all_conflicts_resolved = true;
SEQ_ITERATOR_FOREACH (seq, strips_to_shuffle) {
for (Sequence *seq : strips_to_shuffle) {
LISTBASE_FOREACH (Sequence *, seq_other, seqbasep) {
if (!shuffle_seq_test_overlap(scene, seq, seq_other, offset)) {
continue;
@@ -221,7 +220,7 @@ static int shuffle_seq_time_offset_get(const Scene *scene,
if (SEQ_relation_is_effect_of_strip(seq_other, seq)) {
continue;
}
if (UNLIKELY(SEQ_collection_has_strip(seq_other, strips_to_shuffle))) {
if (UNLIKELY(strips_to_shuffle.contains(seq))) {
CLOG_WARN(&LOG,
"Strip overlaps with itself or another strip, that is to be shuffled. "
"This should never happen.");
@@ -247,8 +246,19 @@ static int shuffle_seq_time_offset_get(const Scene *scene,
return offset;
}
bool SEQ_transform_seqbase_shuffle_time(SeqCollection *strips_to_shuffle,
SeqCollection *time_dependent_strips,
bool SEQ_transform_seqbase_shuffle_time(blender::Span<Sequence *> strips_to_shuffle,
ListBase *seqbasep,
Scene *evil_scene,
ListBase *markers,
const bool use_sync_markers)
{
blender::VectorSet<Sequence *> empty_set;
return SEQ_transform_seqbase_shuffle_time(
strips_to_shuffle, empty_set, seqbasep, evil_scene, markers, use_sync_markers);
}
bool SEQ_transform_seqbase_shuffle_time(blender::Span<Sequence *> strips_to_shuffle,
blender::Span<Sequence *> time_dependent_strips,
ListBase *seqbasep,
Scene *evil_scene,
ListBase *markers,
@@ -259,14 +269,13 @@ bool SEQ_transform_seqbase_shuffle_time(SeqCollection *strips_to_shuffle,
int offset = (-offset_l < offset_r) ? offset_l : offset_r;
if (offset) {
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips_to_shuffle) {
for (Sequence *seq : strips_to_shuffle) {
SEQ_transform_translate_sequence(evil_scene, seq, offset);
seq->flag &= ~SEQ_OVERLAP;
}
if (time_dependent_strips != nullptr) {
SEQ_ITERATOR_FOREACH (seq, time_dependent_strips) {
if (!time_dependent_strips.is_empty()) {
for (Sequence *seq : time_dependent_strips) {
SEQ_offset_animdata(evil_scene, seq, offset);
}
}
@@ -284,111 +293,102 @@ bool SEQ_transform_seqbase_shuffle_time(SeqCollection *strips_to_shuffle,
return offset ? false : true;
}
static SeqCollection *extract_standalone_strips(SeqCollection *transformed_strips)
static blender::VectorSet<Sequence *> extract_standalone_strips(
blender::Span<Sequence *> transformed_strips)
{
SeqCollection *collection = SEQ_collection_create(__func__);
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, transformed_strips) {
blender::VectorSet<Sequence *> standalone_strips;
for (Sequence *seq : transformed_strips) {
if ((seq->type & SEQ_TYPE_EFFECT) == 0 || seq->seq1 == nullptr) {
SEQ_collection_append_strip(seq, collection);
standalone_strips.add(seq);
}
}
return collection;
return standalone_strips;
}
/* Query strips positioned after left edge of transformed strips bound-box. */
static SeqCollection *query_right_side_strips(const Scene *scene,
ListBase *seqbase,
SeqCollection *transformed_strips,
SeqCollection *time_dependent_strips)
static blender::VectorSet<Sequence *> query_right_side_strips(
const Scene *scene,
ListBase *seqbase,
blender::Span<Sequence *> transformed_strips,
blender::Span<Sequence *> time_dependent_strips)
{
int minframe = MAXFRAME;
{
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, transformed_strips) {
for (Sequence *seq : transformed_strips) {
minframe = min_ii(minframe, SEQ_time_left_handle_frame_get(scene, seq));
}
}
SeqCollection *collection = SEQ_collection_create(__func__);
blender::VectorSet<Sequence *> right_side_strips;
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
if (time_dependent_strips != nullptr && SEQ_collection_has_strip(seq, time_dependent_strips)) {
if (!time_dependent_strips.is_empty() && time_dependent_strips.contains(seq)) {
continue;
}
if (SEQ_collection_has_strip(seq, transformed_strips)) {
if (transformed_strips.contains(seq)) {
continue;
}
if ((seq->flag & SELECT) == 0 && SEQ_time_left_handle_frame_get(scene, seq) >= minframe) {
SEQ_collection_append_strip(seq, collection);
right_side_strips.add(seq);
}
}
return collection;
return right_side_strips;
}
/* Offset all strips positioned after left edge of transformed strips bound-box by amount equal
* to overlap of transformed strips. */
static void seq_transform_handle_expand_to_fit(Scene *scene,
ListBase *seqbasep,
SeqCollection *transformed_strips,
SeqCollection *time_dependent_strips,
blender::Span<Sequence *> transformed_strips,
blender::Span<Sequence *> time_dependent_strips,
bool use_sync_markers)
{
ListBase *markers = &scene->markers;
SeqCollection *right_side_strips = query_right_side_strips(
blender::VectorSet right_side_strips = query_right_side_strips(
scene, seqbasep, transformed_strips, time_dependent_strips);
/* Temporarily move right side strips beyond timeline boundary. */
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, right_side_strips) {
for (Sequence *seq : right_side_strips) {
seq->machine += MAXSEQ * 2;
}
/* Shuffle transformed standalone strips. This is because transformed strips can overlap with
* strips on left side. */
SeqCollection *standalone_strips = extract_standalone_strips(transformed_strips);
blender::VectorSet standalone_strips = extract_standalone_strips(transformed_strips);
SEQ_transform_seqbase_shuffle_time(
standalone_strips, time_dependent_strips, seqbasep, scene, markers, use_sync_markers);
SEQ_collection_free(standalone_strips);
/* Move temporarily moved strips back to their original place and tag for shuffling. */
SEQ_ITERATOR_FOREACH (seq, right_side_strips) {
for (Sequence *seq : right_side_strips) {
seq->machine -= MAXSEQ * 2;
}
/* Shuffle again to displace strips on right side. Final effect shuffling is done in
* SEQ_transform_handle_overlap. */
SEQ_transform_seqbase_shuffle_time(
right_side_strips, nullptr, seqbasep, scene, markers, use_sync_markers);
SEQ_collection_free(right_side_strips);
right_side_strips, seqbasep, scene, markers, use_sync_markers);
}
static SeqCollection *query_overwrite_targets(const Scene *scene,
ListBase *seqbasep,
SeqCollection *transformed_strips)
static blender::VectorSet<Sequence *> query_overwrite_targets(
const Scene *scene, ListBase *seqbasep, blender::Span<Sequence *> transformed_strips)
{
SeqCollection *collection = SEQ_query_unselected_strips(seqbasep);
blender::VectorSet<Sequence *> overwrite_targets = SEQ_query_unselected_strips(seqbasep);
Sequence *seq, *seq_transformed;
SEQ_ITERATOR_FOREACH (seq, collection) {
/* Effects of transformed strips can be unselected. These must not be included. */
overwrite_targets.remove_if([&](Sequence *seq) { return transformed_strips.contains(seq); });
overwrite_targets.remove_if([&](Sequence *seq) {
bool does_overlap = false;
SEQ_ITERATOR_FOREACH (seq_transformed, transformed_strips) {
/* Effects of transformed strips can be unselected. These must not be included. */
if (seq == seq_transformed) {
SEQ_collection_remove_strip(seq, collection);
}
for (Sequence *seq_transformed : transformed_strips) {
if (SEQ_transform_test_overlap_seq_seq(scene, seq, seq_transformed)) {
does_overlap = true;
}
}
if (!does_overlap) {
SEQ_collection_remove_strip(seq, collection);
}
}
return !does_overlap;
});
return collection;
return overwrite_targets;
}
enum eOvelapDescrition {
@@ -444,8 +444,8 @@ static void seq_transform_handle_overwrite_split(Scene *scene,
const Sequence *transformed,
Sequence *target)
{
/* Because we are doing a soft split, bmain is not used in SEQ_edit_strip_split, so we can pass
* nullptr here. */
/* Because we are doing a soft split, bmain is not used in SEQ_edit_strip_split, so we can
* pass nullptr here. */
Main *bmain = nullptr;
Sequence *split_strip = SEQ_edit_strip_split(bmain,
@@ -474,17 +474,16 @@ static void seq_transform_handle_overwrite_trim(Scene *scene,
Sequence *target,
const eOvelapDescrition overlap)
{
SeqCollection *targets = SEQ_query_by_reference(
blender::VectorSet targets = SEQ_query_by_reference(
target, scene, seqbasep, SEQ_query_strip_effect_chain);
/* Expand collection by adding all target's children, effects and their children. */
if ((target->type & SEQ_TYPE_EFFECT) != 0) {
SEQ_collection_expand(scene, seqbasep, targets, SEQ_query_strip_effect_chain);
SEQ_iterator_set_expand(scene, seqbasep, targets, SEQ_query_strip_effect_chain);
}
/* Trim all non effects, that have influence on effect length which is overlapping. */
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, targets) {
for (Sequence *seq : targets) {
if ((seq->type & SEQ_TYPE_EFFECT) != 0 && SEQ_effect_get_num_inputs(seq->type) > 0) {
continue;
}
@@ -498,20 +497,17 @@ static void seq_transform_handle_overwrite_trim(Scene *scene,
scene, seq, SEQ_time_left_handle_frame_get(scene, transformed));
}
}
SEQ_collection_free(targets);
}
static void seq_transform_handle_overwrite(Scene *scene,
ListBase *seqbasep,
SeqCollection *transformed_strips)
blender::Span<Sequence *> transformed_strips)
{
SeqCollection *targets = query_overwrite_targets(scene, seqbasep, transformed_strips);
SeqCollection *strips_to_delete = SEQ_collection_create(__func__);
blender::VectorSet targets = query_overwrite_targets(scene, seqbasep, transformed_strips);
blender::VectorSet<Sequence *> strips_to_delete;
Sequence *target;
Sequence *transformed;
SEQ_ITERATOR_FOREACH (target, targets) {
SEQ_ITERATOR_FOREACH (transformed, transformed_strips) {
for (Sequence *target : targets) {
for (Sequence *transformed : transformed_strips) {
if (transformed->machine != target->machine) {
continue;
}
@@ -519,7 +515,7 @@ static void seq_transform_handle_overwrite(Scene *scene,
const eOvelapDescrition overlap = overlap_description_get(scene, transformed, target);
if (overlap == STRIP_OVERLAP_IS_FULL) {
SEQ_collection_append_strip(target, strips_to_delete);
strips_to_delete.add(target);
}
else if (overlap == STRIP_OVERLAP_IS_INSIDE) {
seq_transform_handle_overwrite_split(scene, seqbasep, transformed, target);
@@ -530,39 +526,43 @@ static void seq_transform_handle_overwrite(Scene *scene,
}
}
SEQ_collection_free(targets);
/* Remove covered strips. This must be done in separate loop, because `SEQ_edit_strip_split()`
* also uses `SEQ_edit_remove_flagged_sequences()`. See #91096. */
if (SEQ_collection_len(strips_to_delete) > 0) {
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips_to_delete) {
/* Remove covered strips. This must be done in separate loop, because
* `SEQ_edit_strip_split()` also uses `SEQ_edit_remove_flagged_sequences()`. See #91096. */
if (!strips_to_delete.is_empty()) {
for (Sequence *seq : strips_to_delete) {
SEQ_edit_flag_for_removal(scene, seqbasep, seq);
}
SEQ_edit_remove_flagged_sequences(scene, seqbasep);
}
SEQ_collection_free(strips_to_delete);
}
static void seq_transform_handle_overlap_shuffle(Scene *scene,
ListBase *seqbasep,
SeqCollection *transformed_strips,
SeqCollection *time_dependent_strips,
blender::Span<Sequence *> transformed_strips,
blender::Span<Sequence *> time_dependent_strips,
bool use_sync_markers)
{
ListBase *markers = &scene->markers;
/* Shuffle non strips with no effects attached. */
SeqCollection *standalone_strips = extract_standalone_strips(transformed_strips);
blender::VectorSet standalone_strips = extract_standalone_strips(transformed_strips);
SEQ_transform_seqbase_shuffle_time(
standalone_strips, time_dependent_strips, seqbasep, scene, markers, use_sync_markers);
SEQ_collection_free(standalone_strips);
}
void SEQ_transform_handle_overlap(Scene *scene,
ListBase *seqbasep,
SeqCollection *transformed_strips,
SeqCollection *time_dependent_strips,
blender::Span<Sequence *> transformed_strips,
bool use_sync_markers)
{
blender::VectorSet<Sequence *> empty_set;
SEQ_transform_handle_overlap(scene, seqbasep, transformed_strips, empty_set, use_sync_markers);
}
void SEQ_transform_handle_overlap(Scene *scene,
ListBase *seqbasep,
blender::Span<Sequence *> transformed_strips,
blender::Span<Sequence *> time_dependent_strips,
bool use_sync_markers)
{
const eSeqOverlapMode overlap_mode = SEQ_tool_settings_overlap_mode_get(scene);
@@ -583,8 +583,7 @@ void SEQ_transform_handle_overlap(Scene *scene,
/* If any effects still overlap, we need to move them up.
* In some cases other strips can be overlapping still, see #90646. */
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, transformed_strips) {
for (Sequence *seq : transformed_strips) {
if (SEQ_transform_test_overlap(scene, seqbasep, seq)) {
SEQ_transform_seqbase_shuffle(seqbasep, seq, scene);
}
@@ -739,13 +738,14 @@ void SEQ_image_preview_unit_from_px(const Scene *scene, const float co_src[2], f
co_dst[1] = co_src[1] / scene->r.ysch;
}
void SEQ_image_transform_bounding_box_from_collection(
Scene *scene, SeqCollection *strips, bool apply_rotation, float r_min[2], float r_max[2])
void SEQ_image_transform_bounding_box_from_collection(Scene *scene,
blender::Span<Sequence *> strips,
bool apply_rotation,
float r_min[2],
float r_max[2])
{
Sequence *seq;
INIT_MINMAX2(r_min, r_max);
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
float quad[4][2];
SEQ_image_transform_quad_get(scene, seq, apply_rotation, quad);
for (int i = 0; i < 4; i++) {

View File

@@ -18,6 +18,7 @@
#include "DNA_sequence_types.h"
#include "BLI_blenlib.h"
#include "BLI_vector_set.hh"
#include "BLT_translation.h"
@@ -386,17 +387,15 @@ ListBase *SEQ_get_seqbase_by_seq(const Scene *scene, Sequence *seq)
Sequence *SEQ_get_meta_by_seqbase(ListBase *seqbase_main, ListBase *meta_seqbase)
{
SeqCollection *strips = SEQ_query_all_strips_recursive(seqbase_main);
blender::VectorSet strips = SEQ_query_all_strips_recursive(seqbase_main);
Sequence *seq = nullptr;
SEQ_ITERATOR_FOREACH (seq, strips) {
for (Sequence *seq : strips) {
if (seq->type == SEQ_TYPE_META && &seq->seqbase == meta_seqbase) {
break;
return seq;
}
}
SEQ_collection_free(strips);
return seq;
return nullptr;
}
Sequence *SEQ_sequence_from_strip_elem(ListBase *seqbase, StripElem *se)