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:
committed by
Richard Antalik
parent
93f6001683
commit
3fccfe0bc6
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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. */
|
||||
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user