diff options
author | Richard Antalik <richardantalik@gmail.com> | 2022-06-02 02:39:40 +0300 |
---|---|---|
committer | Richard Antalik <richardantalik@gmail.com> | 2022-06-02 04:16:20 +0300 |
commit | 7afcfe111aacc8bc3f456a3287d3cc34765b798a (patch) | |
tree | a67d26f084938bf9f05289e756654a7b5387d9d1 /source/blender/sequencer/intern | |
parent | 604409b8c7071920e6cc7a672571449070375919 (diff) |
VSE: Make time operations self-contained
This patch makes it possible to manipulate strips without need to use
update functions to recalculate effect and meta strips.
Prior to this change function `SEQ_time_update_sequence` had to be used
to update mainly effects and meta strips. This was implemented in a way
that relied on sorted list of strips, which can't always be done and in
rare cases this approach failed.
In case of meta strips, `seqbase` had to be passed and compared with
"active" one to determine whether meta strip should be updated or not.
This is especially weak system that is prone to bugs when functions are
used by python API functions.
Finally, other strip types had startdisp` and `enddisp` fields updated
by this function and a lot of code relied on these fields even if strip
start, length and offsets are available. This is completely
unnecessary.
Implemented changes:
All effects and meta strips are updated when strip handles are moved or
strip is translated, without need to call any update function.
Function `SEQ_time_update_sequence` has been split to
`SEQ_time_update_meta_strip_range` and
`seq_time_update_effects_strip_range`. These functions should be only
used within sequencer module code. Meta update is used for versioning,
which is only reason for it not being declared internally.
Sequence fields `startdisp` and `enddisp` are now only used for
effects to store strip start and end points. These fields should be
used only internally within sequencer module code.
Use function `SEQ_time_*_handle_frame_get` to get strip start and end
points.
To update effects and meta strips with reasonable performance, cache
for "parent" meta strip and attached effects is added to
`SequenceLookup` cache, so it shares invalidation mechanisms.
All caches are populated during single iteration.
There should be no functional changes.
Differential Revision: https://developer.blender.org/D14990
Diffstat (limited to 'source/blender/sequencer/intern')
-rw-r--r-- | source/blender/sequencer/intern/disk_cache.c | 5 | ||||
-rw-r--r-- | source/blender/sequencer/intern/effects.c | 21 | ||||
-rw-r--r-- | source/blender/sequencer/intern/image_cache.c | 19 | ||||
-rw-r--r-- | source/blender/sequencer/intern/proxy.c | 8 | ||||
-rw-r--r-- | source/blender/sequencer/intern/render.c | 22 | ||||
-rw-r--r-- | source/blender/sequencer/intern/sequence_lookup.c | 94 | ||||
-rw-r--r-- | source/blender/sequencer/intern/sequencer.h | 26 | ||||
-rw-r--r-- | source/blender/sequencer/intern/sound.c | 10 | ||||
-rw-r--r-- | source/blender/sequencer/intern/strip_add.c | 25 | ||||
-rw-r--r-- | source/blender/sequencer/intern/strip_edit.c | 69 | ||||
-rw-r--r-- | source/blender/sequencer/intern/strip_relations.c | 9 | ||||
-rw-r--r-- | source/blender/sequencer/intern/strip_time.c | 217 | ||||
-rw-r--r-- | source/blender/sequencer/intern/strip_time.h | 5 | ||||
-rw-r--r-- | source/blender/sequencer/intern/strip_transform.c | 150 | ||||
-rw-r--r-- | source/blender/sequencer/intern/utils.c | 68 |
15 files changed, 364 insertions, 384 deletions
diff --git a/source/blender/sequencer/intern/disk_cache.c b/source/blender/sequencer/intern/disk_cache.c index f8e8fc32a5d..cc34066c432 100644 --- a/source/blender/sequencer/intern/disk_cache.c +++ b/source/blender/sequencer/intern/disk_cache.c @@ -37,6 +37,7 @@ #include "SEQ_relations.h" #include "SEQ_render.h" #include "SEQ_sequencer.h" +#include "SEQ_time.h" #include "disk_cache.h" #include "image_cache.h" @@ -411,8 +412,8 @@ void seq_disk_cache_invalidate(SeqDiskCache *disk_cache, BLI_mutex_lock(&disk_cache->read_write_mutex); - start = seq_changed->startdisp - DCACHE_IMAGES_PER_FILE; - end = seq_changed->enddisp; + start = SEQ_time_left_handle_frame_get(seq_changed) - DCACHE_IMAGES_PER_FILE; + end = SEQ_time_right_handle_frame_get(seq_changed); seq_disk_cache_delete_invalid_files(disk_cache, scene, seq, invalidate_types, start, end); diff --git a/source/blender/sequencer/intern/effects.c b/source/blender/sequencer/intern/effects.c index d9d21ee3b05..0e5e56908b0 100644 --- a/source/blender/sequencer/intern/effects.c +++ b/source/blender/sequencer/intern/effects.c @@ -49,6 +49,7 @@ #include "SEQ_proxy.h" #include "SEQ_relations.h" #include "SEQ_render.h" +#include "SEQ_time.h" #include "SEQ_utils.h" #include "BLF_api.h" @@ -2431,7 +2432,7 @@ static ImBuf *do_multicam(const SeqRenderData *context, if (!ed) { return NULL; } - ListBase *seqbasep = SEQ_get_seqbase_by_seq(&ed->seqbase, seq); + ListBase *seqbasep = SEQ_get_seqbase_by_seq(context->scene, seq); ListBase *channels = SEQ_get_channels_by_seq(&ed->seqbase, &ed->channels, seq); if (!seqbasep) { return NULL; @@ -2467,13 +2468,15 @@ static ImBuf *do_adjustment_impl(const SeqRenderData *context, Sequence *seq, fl ed = context->scene->ed; - ListBase *seqbasep = SEQ_get_seqbase_by_seq(&ed->seqbase, seq); + ListBase *seqbasep = SEQ_get_seqbase_by_seq(context->scene, seq); ListBase *channels = SEQ_get_channels_by_seq(&ed->seqbase, &ed->channels, seq); /* Clamp timeline_frame to strip range so it behaves as if it had "still frame" offset (last * frame is static after end of strip). This is how most strips behave. This way transition * effects that doesn't overlap or speed effect can't fail rendering outside of strip range. */ - timeline_frame = clamp_i(timeline_frame, seq->startdisp, seq->enddisp - 1); + timeline_frame = clamp_i(timeline_frame, + SEQ_time_left_handle_frame_get(seq), + SEQ_time_right_handle_frame_get(seq) - 1); if (seq->machine > 1) { i = seq_render_give_ibuf_seqbase( @@ -2583,7 +2586,7 @@ static int early_out_speed(Sequence *UNUSED(seq), float UNUSED(fac)) static int seq_effect_speed_get_strip_content_length(const Sequence *seq) { if ((seq->type & SEQ_TYPE_EFFECT) != 0 && SEQ_effect_get_num_inputs(seq->type) == 0) { - return seq->enddisp - seq->startdisp; + return SEQ_time_right_handle_frame_get(seq) - SEQ_time_left_handle_frame_get(seq); } return seq->len; @@ -2610,13 +2613,14 @@ void seq_effect_speed_rebuild_map(Scene *scene, Sequence *seq) MEM_freeN(v->frameMap); } - const int effect_strip_length = seq->enddisp - seq->startdisp; + const int effect_strip_length = SEQ_time_right_handle_frame_get(seq) - + SEQ_time_left_handle_frame_get(seq); v->frameMap = MEM_mallocN(sizeof(float) * effect_strip_length, __func__); v->frameMap[0] = 0.0f; float target_frame = 0; for (int frame_index = 1; frame_index < effect_strip_length; frame_index++) { - target_frame += evaluate_fcurve(fcu, seq->startdisp + frame_index); + target_frame += evaluate_fcurve(fcu, SEQ_time_left_handle_frame_get(seq) + frame_index); CLAMP(target_frame, 0, seq->seq1->len); v->frameMap[frame_index] = target_frame; } @@ -2652,7 +2656,8 @@ float seq_speed_effect_target_frame_get(Scene *scene, /* Only right handle controls effect speed! */ const float target_content_length = seq_effect_speed_get_strip_content_length(source) - source->startofs; - const float speed_effetct_length = seq_speed->enddisp - seq_speed->startdisp; + const float speed_effetct_length = SEQ_time_right_handle_frame_get(seq_speed) - + SEQ_time_left_handle_frame_get(seq_speed); const float ratio = frame_index / speed_effetct_length; target_frame = target_content_length * ratio; break; @@ -3509,7 +3514,7 @@ static void get_default_fac_noop(Sequence *UNUSED(seq), float UNUSED(timeline_fr static void get_default_fac_fade(Sequence *seq, float timeline_frame, float *fac) { - *fac = (float)(timeline_frame - seq->startdisp); + *fac = (float)(timeline_frame - SEQ_time_left_handle_frame_get(seq)); *fac /= seq->len; } diff --git a/source/blender/sequencer/intern/image_cache.c b/source/blender/sequencer/intern/image_cache.c index e1ff0ff64b3..59de24930d6 100644 --- a/source/blender/sequencer/intern/image_cache.c +++ b/source/blender/sequencer/intern/image_cache.c @@ -36,6 +36,7 @@ #include "SEQ_prefetch.h" #include "SEQ_relations.h" #include "SEQ_sequencer.h" +#include "SEQ_time.h" #include "disk_cache.h" #include "image_cache.h" @@ -558,8 +559,9 @@ void seq_cache_free_temp_cache(Scene *scene, short id, int timeline_frame) /* Use frame_index here to avoid freeing raw images if they are used for multiple frames. */ float frame_index = seq_cache_timeline_frame_to_frame_index( key->seq, timeline_frame, key->type); - if (frame_index != key->frame_index || timeline_frame > key->seq->enddisp || - timeline_frame < key->seq->startdisp) { + if (frame_index != key->frame_index || + timeline_frame > SEQ_time_right_handle_frame_get(key->seq) || + timeline_frame < SEQ_time_left_handle_frame_get(key->seq)) { BLI_ghash_remove(cache->hash, key, seq_cache_keyfree, seq_cache_valfree); } } @@ -634,8 +636,8 @@ void seq_cache_cleanup_sequence(Scene *scene, seq_cache_lock(scene); - int range_start = seq_changed->startdisp; - int range_end = seq_changed->enddisp; + int range_start = SEQ_time_left_handle_frame_get(seq_changed); + int range_end = SEQ_time_right_handle_frame_get(seq_changed); if (!force_seq_changed_range) { if (seq->startdisp > range_start) { @@ -668,8 +670,8 @@ void seq_cache_cleanup_sequence(Scene *scene, } if (key->type & invalidate_source && key->seq == seq && - key->timeline_frame >= seq_changed->startdisp && - key->timeline_frame <= seq_changed->enddisp) { + key->timeline_frame >= SEQ_time_left_handle_frame_get(seq_changed) && + key->timeline_frame <= SEQ_time_right_handle_frame_get(seq_changed)) { if (key->link_next || key->link_prev) { seq_cache_relink_keys(key->link_next, key->link_prev); } @@ -700,11 +702,12 @@ void seq_cache_thumbnail_cleanup(Scene *scene, rctf *view_area_safe) SeqCacheKey *key = BLI_ghashIterator_getKey(&gh_iter); BLI_ghashIterator_step(&gh_iter); - const int frame_index = key->timeline_frame - key->seq->startdisp; + const int frame_index = key->timeline_frame - SEQ_time_left_handle_frame_get(key->seq); const int frame_step = SEQ_render_thumbnails_guaranteed_set_frame_step_get(key->seq); const int relative_base_frame = round_fl_to_int((frame_index / (float)frame_step)) * frame_step; - const int nearest_guaranted_absolute_frame = relative_base_frame + key->seq->startdisp; + const int nearest_guaranted_absolute_frame = relative_base_frame + + SEQ_time_left_handle_frame_get(key->seq); if (nearest_guaranted_absolute_frame == key->timeline_frame) { continue; diff --git a/source/blender/sequencer/intern/proxy.c b/source/blender/sequencer/intern/proxy.c index 59b4c6de1ef..464580f5bed 100644 --- a/source/blender/sequencer/intern/proxy.c +++ b/source/blender/sequencer/intern/proxy.c @@ -43,6 +43,7 @@ #include "SEQ_relations.h" #include "SEQ_render.h" #include "SEQ_sequencer.h" +#include "SEQ_time.h" #include "multiview.h" #include "proxy.h" @@ -523,7 +524,9 @@ void SEQ_proxy_rebuild(SeqIndexBuildContext *context, SeqRenderState state; seq_render_state_init(&state); - for (timeline_frame = seq->startdisp; timeline_frame < seq->enddisp; timeline_frame++) { + for (timeline_frame = SEQ_time_left_handle_frame_get(seq); + timeline_frame < SEQ_time_right_handle_frame_get(seq); + timeline_frame++) { if (context->size_flags & IMB_PROXY_25) { seq_proxy_build_frame(&render_context, &state, seq, timeline_frame, 25, overwrite); } @@ -537,7 +540,8 @@ void SEQ_proxy_rebuild(SeqIndexBuildContext *context, seq_proxy_build_frame(&render_context, &state, seq, timeline_frame, 100, overwrite); } - *progress = (float)(timeline_frame - seq->startdisp) / (seq->enddisp - seq->startdisp); + *progress = (float)(timeline_frame - SEQ_time_left_handle_frame_get(seq)) / + (SEQ_time_right_handle_frame_get(seq) - SEQ_time_left_handle_frame_get(seq)); *do_update = true; if (*stop || G.is_break) { diff --git a/source/blender/sequencer/intern/render.c b/source/blender/sequencer/intern/render.c index b0898be3765..e7a1bbeb9d0 100644 --- a/source/blender/sequencer/intern/render.c +++ b/source/blender/sequencer/intern/render.c @@ -1994,11 +1994,12 @@ ImBuf *SEQ_render_give_ibuf_direct(const SeqRenderData *context, float SEQ_render_thumbnail_first_frame_get(Sequence *seq, float frame_step, rctf *view_area) { - int first_drawable_frame = max_iii(seq->startdisp, seq->start, view_area->xmin); + int first_drawable_frame = max_iii( + SEQ_time_left_handle_frame_get(seq), seq->start, view_area->xmin); /* First frame should correspond to handle position. */ - if (first_drawable_frame == seq->startdisp) { - return seq->startdisp; + if (first_drawable_frame == SEQ_time_left_handle_frame_get(seq)) { + return SEQ_time_left_handle_frame_get(seq); } float aligned_frame_offset = (int)((first_drawable_frame - seq->start) / frame_step) * @@ -2011,7 +2012,7 @@ float SEQ_render_thumbnail_next_frame_get(Sequence *seq, float last_frame, float float next_frame = last_frame + frame_step; /* If handle position was displayed, align next frame with `seq->start`. */ - if (last_frame == seq->startdisp) { + if (last_frame == SEQ_time_left_handle_frame_get(seq)) { next_frame = seq->start + ((int)((last_frame - seq->start) / frame_step) + 1) * frame_step; } @@ -2088,8 +2089,9 @@ void SEQ_render_thumbnails(const SeqRenderData *context, /* Adding the hold offset value (seq->anim_startofs) to the start frame. Position of image not * affected, but frame loaded affected. */ - float upper_thumb_bound = SEQ_time_has_right_still_frames(seq) ? (seq->start + seq->len) : - seq->enddisp; + float upper_thumb_bound = SEQ_time_has_right_still_frames(seq) ? + (seq->start + seq->len) : + SEQ_time_right_handle_frame_get(seq); upper_thumb_bound = (upper_thumb_bound > view_area->xmax) ? view_area->xmax + frame_step : upper_thumb_bound; @@ -2122,8 +2124,8 @@ void SEQ_render_thumbnails(const SeqRenderData *context, int SEQ_render_thumbnails_guaranteed_set_frame_step_get(const Sequence *seq) { - const int content_start = max_ii(seq->startdisp, seq->start); - const int content_end = min_ii(seq->enddisp, seq->start + seq->len); + const int content_start = max_ii(SEQ_time_left_handle_frame_get(seq), seq->start); + const int content_end = min_ii(SEQ_time_right_handle_frame_get(seq), seq->start + seq->len); const int content_len = content_end - content_start; /* Arbitrary, but due to performance reasons should be as low as possible. */ @@ -2143,10 +2145,10 @@ void SEQ_render_thumbnails_base_set(const SeqRenderData *context, SeqRenderState state; seq_render_state_init(&state); - int timeline_frame = seq->startdisp; + int timeline_frame = SEQ_time_left_handle_frame_get(seq); const int frame_step = SEQ_render_thumbnails_guaranteed_set_frame_step_get(seq); - while (timeline_frame < seq->enddisp && !*stop) { + while (timeline_frame < SEQ_time_right_handle_frame_get(seq) && !*stop) { ImBuf *ibuf = seq_cache_get( context, seq_orig, roundf(timeline_frame), SEQ_CACHE_STORE_THUMBNAIL); if (ibuf) { diff --git a/source/blender/sequencer/intern/sequence_lookup.c b/source/blender/sequencer/intern/sequence_lookup.c index 2a2626d8abf..22c1ce39f4f 100644 --- a/source/blender/sequencer/intern/sequence_lookup.c +++ b/source/blender/sequencer/intern/sequence_lookup.c @@ -6,6 +6,7 @@ */ #include "SEQ_sequencer.h" +#include "sequencer.h" #include "DNA_listBase.h" #include "DNA_scene_types.h" @@ -14,6 +15,7 @@ #include "SEQ_iterator.h" #include "BLI_ghash.h" +#include "BLI_listbase.h" #include "BLI_string.h" #include "BLI_sys_types.h" #include "BLI_threads.h" @@ -24,24 +26,66 @@ static ThreadMutex lookup_lock = BLI_MUTEX_INITIALIZER; typedef struct SequenceLookup { - GHash *by_name; + GHash *seq_by_name; + GHash *meta_by_seq; + GHash *effects_by_seq; eSequenceLookupTag tag; } SequenceLookup; static void seq_sequence_lookup_init(struct SequenceLookup *lookup) { - lookup->by_name = BLI_ghash_str_new(__func__); + 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_build(const struct Scene *scene, struct SequenceLookup *lookup) +static void seq_sequence_lookup_append_effect(Sequence *input, + Sequence *effect, + struct SequenceLookup *lookup) +{ + if (input == NULL) { + return; + } + + SeqCollection *effects = BLI_ghash_lookup(lookup->effects_by_seq, input); + if (effects == NULL) { + effects = SEQ_collection_create(__func__); + BLI_ghash_insert(lookup->effects_by_seq, input, effects); + } + + SEQ_collection_append_strip(effect, effects); +} + +static void seq_sequence_lookup_build_effect(Sequence *seq, struct SequenceLookup *lookup) { - SeqCollection *all_strips = SEQ_query_all_strips_recursive(&scene->ed->seqbase); - Sequence *seq; - SEQ_ITERATOR_FOREACH (seq, all_strips) { - BLI_ghash_insert(lookup->by_name, seq->name + 2, seq); + if ((seq->type & SEQ_TYPE_EFFECT) == 0) { + return; } - SEQ_collection_free(all_strips); + + seq_sequence_lookup_append_effect(seq->seq1, seq, lookup); + seq_sequence_lookup_append_effect(seq->seq2, seq, lookup); +} + +static void seq_sequence_lookup_build_from_seqbase(Sequence *parent_meta, + const ListBase *seqbase, + struct SequenceLookup *lookup) +{ + LISTBASE_FOREACH (Sequence *, seq, seqbase) { + BLI_ghash_insert(lookup->seq_by_name, seq->name + 2, seq); + BLI_ghash_insert(lookup->meta_by_seq, seq, parent_meta); + seq_sequence_lookup_build_effect(seq, lookup); + + if (seq->type == SEQ_TYPE_META) { + seq_sequence_lookup_build_from_seqbase(seq, &seq->seqbase, lookup); + } + } +} + +static void seq_sequence_lookup_build(const struct Scene *scene, struct SequenceLookup *lookup) +{ + Editing *ed = SEQ_editing_get(scene); + seq_sequence_lookup_build_from_seqbase(NULL, &ed->seqbase, lookup); lookup->tag &= ~SEQ_LOOKUP_TAG_INVALID; } @@ -58,8 +102,12 @@ static void seq_sequence_lookup_free(struct SequenceLookup **lookup) return; } - BLI_ghash_free((*lookup)->by_name, NULL, NULL); - (*lookup)->by_name = NULL; + BLI_ghash_free((*lookup)->seq_by_name, NULL, NULL); + BLI_ghash_free((*lookup)->meta_by_seq, NULL, NULL); + BLI_ghash_free((*lookup)->effects_by_seq, NULL, SEQ_collection_free); + (*lookup)->seq_by_name = NULL; + (*lookup)->meta_by_seq = NULL; + (*lookup)->effects_by_seq = NULL; MEM_freeN(*lookup); *lookup = NULL; } @@ -98,17 +146,39 @@ void SEQ_sequence_lookup_free(const Scene *scene) BLI_mutex_unlock(&lookup_lock); } -Sequence *SEQ_sequence_lookup_by_name(const Scene *scene, const char *key) +Sequence *SEQ_sequence_lookup_seq_by_name(const Scene *scene, const char *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; + Sequence *seq = BLI_ghash_lookup(lookup->seq_by_name, key); + BLI_mutex_unlock(&lookup_lock); + return seq; +} + +Sequence *seq_sequence_lookup_meta_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; - Sequence *seq = BLI_ghash_lookup(lookup->by_name, key); + Sequence *seq = BLI_ghash_lookup(lookup->meta_by_seq, key); BLI_mutex_unlock(&lookup_lock); return seq; } +SeqCollection *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 = BLI_ghash_lookup(lookup->effects_by_seq, key); + BLI_mutex_unlock(&lookup_lock); + return effects; +} + void SEQ_sequence_lookup_tag(const Scene *scene, eSequenceLookupTag tag) { if (!scene->ed) { diff --git a/source/blender/sequencer/intern/sequencer.h b/source/blender/sequencer/intern/sequencer.h index 9f5bdf672c0..5e78c8c6f96 100644 --- a/source/blender/sequencer/intern/sequencer.h +++ b/source/blender/sequencer/intern/sequencer.h @@ -14,13 +14,37 @@ extern "C" { 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. */ void seq_free_sequence_recurse(struct Scene *scene, struct Sequence *seq, bool do_id_user); struct StripProxy *seq_strip_proxy_alloc(void); - +/** + * Find meta strip, that contains strip `key`. + * If lookup hash doesn't exist, it will be created. If hash is tagged as invalid, it will be + * rebuilt. + * + * \param scene: scene that owns lookup hash + * \param key: pointer to Sequence inside of meta strip + * + * \return pointer to meta strip + */ +struct Sequence *seq_sequence_lookup_meta_by_seq(const struct Scene *scene, + const struct Sequence *key); +/** + * Find effect strips, that use strip `seq` as one of inputs. + * If lookup hash doesn't exist, it will be created. If hash is tagged as invalid, it will be + * rebuilt. + * + * \param scene: scene that owns lookup hash + * \param key: pointer to Sequence inside of meta strip + * + * \return collection of effect strips + */ +struct SeqCollection *seq_sequence_lookup_effects_by_seq(const struct Scene *scene, + const struct Sequence *key); #ifdef __cplusplus } #endif diff --git a/source/blender/sequencer/intern/sound.c b/source/blender/sequencer/intern/sound.c index 8076c600560..50c8b76a9a0 100644 --- a/source/blender/sequencer/intern/sound.c +++ b/source/blender/sequencer/intern/sound.c @@ -35,7 +35,6 @@ static bool sequencer_refresh_sound_length_recursive(Main *bmain, Scene *scene, for (seq = seqbase->first; seq; seq = seq->next) { if (seq->type == SEQ_TYPE_META) { if (sequencer_refresh_sound_length_recursive(bmain, scene, &seq->seqbase)) { - SEQ_time_update_sequence(scene, seqbase, seq); changed = true; } } @@ -55,7 +54,6 @@ static bool sequencer_refresh_sound_length_recursive(Main *bmain, Scene *scene, seq->endofs *= fac; seq->start += (old - seq->startofs); /* So that visual/"real" start frame does not change! */ - SEQ_time_update_sequence(scene, seqbase, seq); changed = true; } } @@ -99,8 +97,12 @@ void SEQ_sound_update_bounds(Scene *scene, Sequence *seq) /* We have to take into account start frame of the sequence's scene! */ int startofs = seq->startofs + seq->anim_startofs + seq->scene->r.sfra; - BKE_sound_move_scene_sound( - scene, seq->scene_sound, seq->startdisp, seq->enddisp, startofs, 0.0); + BKE_sound_move_scene_sound(scene, + seq->scene_sound, + SEQ_time_left_handle_frame_get(seq), + SEQ_time_right_handle_frame_get(seq), + startofs, + 0.0); } } else { diff --git a/source/blender/sequencer/intern/strip_add.c b/source/blender/sequencer/intern/strip_add.c index 77b0fc946d9..bb812302464 100644 --- a/source/blender/sequencer/intern/strip_add.c +++ b/source/blender/sequencer/intern/strip_add.c @@ -51,6 +51,8 @@ #include "multiview.h" #include "proxy.h" +#include "sequencer.h" +#include "strip_time.h" #include "utils.h" void SEQ_add_load_data_init(SeqLoadData *load_data, @@ -73,9 +75,9 @@ void SEQ_add_load_data_init(SeqLoadData *load_data, static void seq_add_generic_update(Scene *scene, ListBase *seqbase, Sequence *seq) { SEQ_sequence_base_unique_name_recursive(scene, &scene->ed->seqbase, seq); - SEQ_time_update_sequence(scene, seqbase, seq); - SEQ_sort(seqbase); SEQ_relations_invalidate_cache_composite(scene, seq); + SEQ_sequence_lookup_tag(scene, SEQ_LOOKUP_TAG_INVALID); + SEQ_time_update_meta_strip_range(scene, seq_sequence_lookup_meta_by_seq(scene, seq)); } static void seq_add_set_name(Scene *scene, Sequence *seq, SeqLoadData *load_data) @@ -174,11 +176,12 @@ Sequence *SEQ_add_effect_strip(Scene *scene, ListBase *seqbase, struct SeqLoadDa if (!load_data->effect.seq1) { seq->len = 1; /* Effect is generator, set non zero length. */ - SEQ_time_right_handle_frame_set(seq, load_data->effect.end_frame); + SEQ_time_right_handle_frame_set(scene, seq, load_data->effect.end_frame); } seq_add_set_name(scene, seq, load_data); seq_add_generic_update(scene, seqbase, seq); + seq_time_effect_range_set(seq); return seq; } @@ -362,7 +365,6 @@ Sequence *SEQ_add_meta_strip(Scene *scene, ListBase *seqbase, SeqLoadData *load_ /* Set frames start and length. */ seqm->start = load_data->start_frame; seqm->len = 1; - SEQ_time_update_sequence(scene, seqbase, seqm); return seqm; } @@ -509,11 +511,8 @@ void SEQ_add_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, const boo if (lock_range) { /* keep so we don't have to move the actual start and end points (only the data) */ - Editing *ed = SEQ_editing_get(scene); - ListBase *seqbase = SEQ_get_seqbase_by_seq(&ed->seqbase, seq); - SEQ_time_update_sequence(scene, seqbase, seq); - prev_startdisp = seq->startdisp; - prev_enddisp = seq->enddisp; + prev_startdisp = SEQ_time_left_handle_frame_get(seq); + prev_enddisp = SEQ_time_right_handle_frame_get(seq); } switch (seq->type) { @@ -656,13 +655,11 @@ void SEQ_add_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, const boo free_proxy_seq(seq); if (lock_range) { - SEQ_time_left_handle_frame_set(seq, prev_startdisp); - SEQ_time_right_handle_frame_set(seq, prev_enddisp); - SEQ_transform_fix_single_image_seq_offsets(seq); + SEQ_time_left_handle_frame_set(scene, seq, prev_startdisp); + SEQ_time_right_handle_frame_set(scene, seq, prev_enddisp); + SEQ_transform_fix_single_image_seq_offsets(scene, seq); } - ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(scene)); - SEQ_time_update_sequence(scene, seqbase, seq); SEQ_relations_invalidate_cache_raw(scene, seq); } diff --git a/source/blender/sequencer/intern/strip_edit.c b/source/blender/sequencer/intern/strip_edit.c index 96bfce8f740..7965615e188 100644 --- a/source/blender/sequencer/intern/strip_edit.c +++ b/source/blender/sequencer/intern/strip_edit.c @@ -84,8 +84,8 @@ int SEQ_edit_sequence_swap(Sequence *seq_a, Sequence *seq_b, const char **error_ SWAP(int, seq_a->startofs, seq_b->startofs); SWAP(int, seq_a->endofs, seq_b->endofs); SWAP(int, seq_a->machine, seq_b->machine); - SWAP(int, seq_a->startdisp, seq_b->startdisp); - SWAP(int, seq_a->enddisp, seq_b->enddisp); + seq_time_effect_range_set(seq_a); + seq_time_effect_range_set(seq_b); return 1; } @@ -230,7 +230,7 @@ bool SEQ_edit_move_strip_to_meta(Scene *scene, { /* Find the appropriate seqbase */ Editing *ed = SEQ_editing_get(scene); - ListBase *seqbase = SEQ_get_seqbase_by_seq(&ed->seqbase, src_seq); + ListBase *seqbase = SEQ_get_seqbase_by_seq(scene, src_seq); if (dst_seqm->type != SEQ_TYPE_META) { *error_str = N_("Can not move strip to non-meta strip"); @@ -272,11 +272,11 @@ bool SEQ_edit_move_strip_to_meta(Scene *scene, return true; } -static void seq_split_set_left_hold_offset(Sequence *seq, int timeline_frame) +static void seq_split_set_left_hold_offset(const Scene *scene, Sequence *seq, int timeline_frame) { /* Adjust within range of extended stillframes before strip. */ if (timeline_frame < seq->start) { - SEQ_time_left_handle_frame_set(seq, timeline_frame); + SEQ_time_left_handle_frame_set(scene, seq, timeline_frame); } /* Adjust within range of strip contents. */ else if ((timeline_frame >= seq->start) && (timeline_frame <= (seq->start + seq->len))) { @@ -290,19 +290,19 @@ static void seq_split_set_left_hold_offset(Sequence *seq, int timeline_frame) seq->start += timeline_frame - seq->start; seq->anim_startofs += seq->len - 1; seq->len = 1; - SEQ_time_left_handle_frame_set(seq, timeline_frame); - SEQ_time_right_handle_frame_set(seq, right_handle_backup); + SEQ_time_left_handle_frame_set(scene, seq, timeline_frame); + SEQ_time_right_handle_frame_set(scene, seq, right_handle_backup); } } -static void seq_split_set_right_hold_offset(Sequence *seq, int timeline_frame) +static void seq_split_set_right_hold_offset(const Scene *scene, Sequence *seq, int timeline_frame) { /* Adjust within range of extended stillframes before strip. */ if (timeline_frame < seq->start) { const int left_handle_backup = SEQ_time_left_handle_frame_get(seq); seq->start = timeline_frame - 1; - SEQ_time_left_handle_frame_set(seq, left_handle_backup); - SEQ_time_right_handle_frame_set(seq, timeline_frame); + SEQ_time_left_handle_frame_set(scene, seq, left_handle_backup); + SEQ_time_right_handle_frame_set(scene, seq, timeline_frame); } /* Adjust within range of strip contents. */ else if ((timeline_frame >= seq->start) && (timeline_frame <= (seq->start + seq->len))) { @@ -311,11 +311,11 @@ static void seq_split_set_right_hold_offset(Sequence *seq, int timeline_frame) } /* Adjust within range of extended stillframes after strip. */ else if ((seq->start + seq->len) < timeline_frame) { - SEQ_time_right_handle_frame_set(seq, timeline_frame); + SEQ_time_right_handle_frame_set(scene, seq, timeline_frame); } } -static void seq_split_set_right_offset(Sequence *seq, int timeline_frame) +static void seq_split_set_right_offset(const Scene *scene, Sequence *seq, int timeline_frame) { /* Adjust within range of extended stillframes before strip. */ if (timeline_frame < seq->start) { @@ -324,10 +324,10 @@ static void seq_split_set_right_offset(Sequence *seq, int timeline_frame) seq->startofs += content_offset; } - SEQ_time_right_handle_frame_set(seq, timeline_frame); + SEQ_time_right_handle_frame_set(scene, seq, timeline_frame); } -static void seq_split_set_left_offset(Sequence *seq, int timeline_frame) +static void seq_split_set_left_offset(const Scene *scene, Sequence *seq, int timeline_frame) { /* Adjust within range of extended stillframes after strip. */ if (timeline_frame > seq->start + seq->len) { @@ -336,12 +336,13 @@ static void seq_split_set_left_offset(Sequence *seq, int timeline_frame) seq->endofs += content_offset; } - SEQ_time_left_handle_frame_set(seq, timeline_frame); + SEQ_time_left_handle_frame_set(scene, seq, timeline_frame); } static bool seq_edit_split_effect_intersect_check(const Sequence *seq, const int timeline_frame) { - return timeline_frame > seq->startdisp && timeline_frame < seq->enddisp; + return timeline_frame > SEQ_time_left_handle_frame_get(seq) && + timeline_frame < SEQ_time_right_handle_frame_get(seq); } static void seq_edit_split_handle_strip_offsets(Main *bmain, @@ -355,27 +356,25 @@ static void seq_edit_split_handle_strip_offsets(Main *bmain, if (seq_edit_split_effect_intersect_check(right_seq, timeline_frame)) { switch (method) { case SEQ_SPLIT_SOFT: - seq_split_set_left_offset(right_seq, timeline_frame); + seq_split_set_left_offset(scene, right_seq, timeline_frame); break; case SEQ_SPLIT_HARD: - seq_split_set_left_hold_offset(right_seq, timeline_frame); + seq_split_set_left_hold_offset(scene, right_seq, timeline_frame); SEQ_add_reload_new_file(bmain, scene, right_seq, false); break; } - SEQ_time_update_sequence(scene, seqbase, right_seq); } if (seq_edit_split_effect_intersect_check(left_seq, timeline_frame)) { switch (method) { case SEQ_SPLIT_SOFT: - seq_split_set_right_offset(left_seq, timeline_frame); + seq_split_set_right_offset(scene, left_seq, timeline_frame); break; case SEQ_SPLIT_HARD: - seq_split_set_right_hold_offset(left_seq, timeline_frame); + seq_split_set_right_hold_offset(scene, left_seq, timeline_frame); SEQ_add_reload_new_file(bmain, scene, left_seq, false); break; } - SEQ_time_update_sequence(scene, seqbase, left_seq); } } @@ -468,10 +467,6 @@ Sequence *SEQ_edit_strip_split(Main *bmain, SEQ_collection_free(collection); - /* Sort list, so that no strip can depend on next strip in list. - * This is important for SEQ_time_update_sequence functionality. */ - SEQ_sort(&left_strips); - /* Duplicate ListBase. */ ListBase right_strips = {NULL, NULL}; SEQ_sequence_base_dupli_recursive(scene, scene, &right_strips, &left_strips, SEQ_DUPE_ALL, 0); @@ -480,18 +475,23 @@ Sequence *SEQ_edit_strip_split(Main *bmain, Sequence *right_seq = right_strips.first; Sequence *return_seq = NULL; - /* Move strips from detached `ListBase`, otherwise they can't be flagged for removal, - * SEQ_time_update_sequence can fail to update meta strips and they can't be renamed. - * This is because these functions check all strips in `Editing` to manage relationships. */ + /* Move strips from detached `ListBase`, otherwise they can't be flagged for removal. */ BLI_movelisttolist(seqbase, &left_strips); BLI_movelisttolist(seqbase, &right_strips); + /* Rename duplicated strips. This has to be done immediately after adding + * strips to seqbase, for lookup cache to work correctly. */ + Sequence *seq_rename = right_seq; + for (; seq_rename; seq_rename = seq_rename->next) { + SEQ_ensure_unique_name(seq_rename, scene); + } + /* Split strips. */ while (left_seq && right_seq) { - if (left_seq->startdisp >= timeline_frame) { + if (SEQ_time_left_handle_frame_get(left_seq) >= timeline_frame) { SEQ_edit_flag_for_removal(scene, seqbase, left_seq); } - if (right_seq->enddisp <= timeline_frame) { + else if (SEQ_time_right_handle_frame_get(right_seq) <= timeline_frame) { SEQ_edit_flag_for_removal(scene, seqbase, right_seq); } else if (return_seq == NULL) { @@ -506,13 +506,6 @@ Sequence *SEQ_edit_strip_split(Main *bmain, } SEQ_edit_remove_flagged_sequences(scene, seqbase); - - /* Rename duplicated strips. */ - Sequence *seq_rename = return_seq; - for (; seq_rename; seq_rename = seq_rename->next) { - SEQ_ensure_unique_name(seq_rename, scene); - } - SEQ_animation_restore_original(scene, &fcurves_original_backup); return return_seq; diff --git a/source/blender/sequencer/intern/strip_relations.c b/source/blender/sequencer/intern/strip_relations.c index 1899cc99263..4acf2763ce5 100644 --- a/source/blender/sequencer/intern/strip_relations.c +++ b/source/blender/sequencer/intern/strip_relations.c @@ -47,7 +47,8 @@ static bool seq_relations_check_depend(Sequence *seq, Sequence *cur) } /* sequences are not intersecting in time, assume no dependency exists between them */ - if (cur->enddisp < seq->startdisp || cur->startdisp > seq->enddisp) { + if (SEQ_time_right_handle_frame_get(cur) < SEQ_time_left_handle_frame_get(seq) || + SEQ_time_left_handle_frame_get(cur) > SEQ_time_right_handle_frame_get(seq)) { return false; } @@ -290,8 +291,8 @@ static void sequencer_all_free_anim_ibufs(Editing *ed, } else { /* Limit frame range to meta strip. */ - meta_range[0] = max_ii(frame_range[0], seq->startdisp); - meta_range[1] = min_ii(frame_range[1], seq->enddisp); + meta_range[0] = max_ii(frame_range[0], SEQ_time_left_handle_frame_get(seq)); + meta_range[1] = min_ii(frame_range[1], SEQ_time_right_handle_frame_get(seq)); } sequencer_all_free_anim_ibufs(ed, &seq->seqbase, timeline_frame, meta_range); @@ -345,7 +346,7 @@ bool SEQ_relations_check_scene_recursion(Scene *scene, ReportList *reports) RPT_WARNING, "Recursion detected in video sequencer. Strip %s at frame %d will not be rendered", recursive_seq->name + 2, - recursive_seq->startdisp); + SEQ_time_left_handle_frame_get(recursive_seq)); LISTBASE_FOREACH (Sequence *, seq, &ed->seqbase) { if (seq->type != SEQ_TYPE_SCENE && sequencer_seq_generates_image(seq)) { diff --git a/source/blender/sequencer/intern/strip_time.c b/source/blender/sequencer/intern/strip_time.c index e4f7a5e87e8..25d4f08be82 100644 --- a/source/blender/sequencer/intern/strip_time.c +++ b/source/blender/sequencer/intern/strip_time.c @@ -27,6 +27,7 @@ #include "SEQ_time.h" #include "SEQ_transform.h" +#include "sequencer.h" #include "strip_time.h" #include "utils.h" @@ -37,7 +38,7 @@ float seq_give_frame_index(Sequence *seq, float timeline_frame) int end = seq->start + seq->len - 1; if (seq->type & SEQ_TYPE_EFFECT) { - end = seq->enddisp; + end = SEQ_time_right_handle_frame_get(seq); } if (end < sta) { @@ -89,7 +90,7 @@ static int metaseq_end(Sequence *metaseq) return metaseq->start + metaseq->len - metaseq->endofs; } -static void seq_update_sound_bounds_recursive_impl(Scene *scene, +static void seq_update_sound_bounds_recursive_impl(const Scene *scene, Sequence *metaseq, int start, int end) @@ -131,33 +132,31 @@ static void seq_update_sound_bounds_recursive_impl(Scene *scene, } } -void seq_update_sound_bounds_recursive(Scene *scene, Sequence *metaseq) +void seq_update_sound_bounds_recursive(const Scene *scene, Sequence *metaseq) { seq_update_sound_bounds_recursive_impl( scene, metaseq, metaseq_start(metaseq), metaseq_end(metaseq)); } -static void seq_time_update_sequence_bounds(Scene *scene, Sequence *seq) +/* Update meta strip content start and end, update sound playback range. */ +void SEQ_time_update_meta_strip_range(const Scene *scene, Sequence *seq_meta) { - seq->startdisp = seq->start + seq->startofs; - seq->enddisp = seq->start + seq->len - seq->endofs; - - if (seq->type == SEQ_TYPE_META) { - seq_update_sound_bounds_recursive(scene, seq); + if (seq_meta == NULL) { + return; } -} -static void seq_time_update_meta_strip(Scene *scene, Sequence *seq_meta) -{ if (BLI_listbase_is_empty(&seq_meta->seqbase)) { return; } + const int strip_start = SEQ_time_left_handle_frame_get(seq_meta); + const int strip_end = SEQ_time_right_handle_frame_get(seq_meta); + int min = MAXFRAME * 2; int max = -MAXFRAME * 2; LISTBASE_FOREACH (Sequence *, seq, &seq_meta->seqbase) { - min = min_ii(seq->startdisp, min); - max = max_ii(seq->enddisp, max); + min = min_ii(SEQ_time_left_handle_frame_get(seq), min); + max = max_ii(SEQ_time_right_handle_frame_get(seq), max); } seq_meta->start = min + seq_meta->anim_startofs; @@ -166,144 +165,54 @@ static void seq_time_update_meta_strip(Scene *scene, Sequence *seq_meta) seq_meta->len -= seq_meta->anim_endofs; seq_update_sound_bounds_recursive(scene, seq_meta); -} - -void SEQ_time_update_meta_strip_range(Scene *scene, Sequence *seq_meta) -{ - if (seq_meta == NULL) { - return; - } - - seq_time_update_meta_strip(scene, seq_meta); /* Prevent meta-strip to move in timeline. */ - SEQ_time_left_handle_frame_set(seq_meta, seq_meta->startdisp); - SEQ_time_right_handle_frame_set(seq_meta, seq_meta->enddisp); + SEQ_time_left_handle_frame_set(scene, seq_meta, strip_start); + SEQ_time_right_handle_frame_set(scene, seq_meta, strip_end); } -void SEQ_time_update_sequence(Scene *scene, ListBase *seqbase, Sequence *seq) +void seq_time_effect_range_set(Sequence *seq) { - Sequence *seqm; - - /* Check all meta-strips recursively. */ - seqm = seq->seqbase.first; - while (seqm) { - if (seqm->seqbase.first) { - SEQ_time_update_sequence(scene, &seqm->seqbase, seqm); - } - seqm = seqm->next; + if (seq->seq1 && seq->seq2) { /* 2 - input effect. */ + seq->startdisp = max_ii(SEQ_time_left_handle_frame_get(seq->seq1), + SEQ_time_left_handle_frame_get(seq->seq2)); + seq->enddisp = min_ii(SEQ_time_right_handle_frame_get(seq->seq1), + SEQ_time_right_handle_frame_get(seq->seq2)); } - - /* effects and meta: automatic start and end */ - if (seq->type & SEQ_TYPE_EFFECT) { - if (seq->seq1) { - seq->startofs = seq->endofs = 0; - if (seq->seq3) { - seq->start = seq->startdisp = max_iii( - seq->seq1->startdisp, seq->seq2->startdisp, seq->seq3->startdisp); - seq->enddisp = min_iii(seq->seq1->enddisp, seq->seq2->enddisp, seq->seq3->enddisp); - } - else if (seq->seq2) { - seq->start = seq->startdisp = max_ii(seq->seq1->startdisp, seq->seq2->startdisp); - seq->enddisp = min_ii(seq->seq1->enddisp, seq->seq2->enddisp); - } - else { - seq->start = seq->startdisp = seq->seq1->startdisp; - seq->enddisp = seq->seq1->enddisp; - } - /* we can't help if strips don't overlap, it won't give useful results. - * but at least ensure 'len' is never negative which causes bad bugs elsewhere. */ - if (seq->enddisp < seq->startdisp) { - /* simple start/end swap */ - seq->start = seq->enddisp; - seq->enddisp = seq->startdisp; - seq->startdisp = seq->start; - seq->flag |= SEQ_INVALID_EFFECT; - } - else { - seq->flag &= ~SEQ_INVALID_EFFECT; - } - - seq->len = seq->enddisp - seq->startdisp; - } - else { - seq_time_update_sequence_bounds(scene, seq); - } + else if (seq->seq1) { /* Single input effect. */ + seq->startdisp = SEQ_time_right_handle_frame_get(seq->seq1); + seq->enddisp = SEQ_time_left_handle_frame_get(seq->seq1); } - else if (seq->type == SEQ_TYPE_META) { - seq_time_update_meta_strip(scene, seq); + else if (seq->seq2) { /* Strip may be missing one of inputs. */ + seq->startdisp = SEQ_time_right_handle_frame_get(seq->seq2); + seq->enddisp = SEQ_time_left_handle_frame_get(seq->seq2); } - else { - seq_time_update_sequence_bounds(scene, seq); - } - - Editing *ed = SEQ_editing_get(scene); - /* Strip is inside meta strip */ - if (seqbase != &ed->seqbase) { - Sequence *meta = SEQ_get_meta_by_seqbase(&ed->seqbase, seqbase); - SEQ_time_update_meta_strip_range(scene, meta); + if (seq->startdisp > seq->enddisp) { + SWAP(int, seq->startdisp, seq->enddisp); } - seq_time_update_sequence_bounds(scene, seq); + /* Values unusable for effects, these should be always 0. */ + seq->startofs = seq->endofs = seq->anim_startofs = seq->anim_endofs = 0; } -static bool update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *changed_seq) +/* Update strip startdisp and enddisp (n-input effects have no len to calculate these). */ +void seq_time_update_effects_strip_range(const Scene *scene, SeqCollection *effects) { - Sequence *subseq; - bool do_update = false; - - /* recurse downwards to see if this seq depends on the changed seq */ - - if (seq == NULL) { - return false; - } - - if (seq == changed_seq) { - do_update = true; - } - - for (subseq = seq->seqbase.first; subseq; subseq = subseq->next) { - if (update_changed_seq_recurs(scene, subseq, changed_seq)) { - do_update = true; - } - } - - if (seq->seq1) { - if (update_changed_seq_recurs(scene, seq->seq1, changed_seq)) { - do_update = true; - } - } - if (seq->seq2 && (seq->seq2 != seq->seq1)) { - if (update_changed_seq_recurs(scene, seq->seq2, changed_seq)) { - do_update = true; - } - } - if (seq->seq3 && (seq->seq3 != seq->seq1) && (seq->seq3 != seq->seq2)) { - if (update_changed_seq_recurs(scene, seq->seq3, changed_seq)) { - do_update = true; - } - } - - if (do_update) { - ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(scene)); - SEQ_time_update_sequence(scene, seqbase, seq); + if (effects == NULL) { + return; } - return do_update; -} - -void SEQ_time_update_recursive(Scene *scene, Sequence *changed_seq) -{ - Editing *ed = SEQ_editing_get(scene); Sequence *seq; - - if (ed == NULL) { - return; + /* First pass: Update length of immediate effects. */ + SEQ_ITERATOR_FOREACH (seq, effects) { + seq_time_effect_range_set(seq); } - for (seq = ed->seqbase.first; seq; seq = seq->next) { - update_changed_seq_recurs(scene, seq, changed_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)); } } @@ -342,12 +251,14 @@ int SEQ_time_find_next_prev_edit(Scene *scene, } if (do_center) { - seq_frames[0] = (seq->startdisp + seq->enddisp) / 2; + seq_frames[0] = (SEQ_time_left_handle_frame_get(seq) + + SEQ_time_right_handle_frame_get(seq)) / + 2; seq_frames_tot = 1; } else { - seq_frames[0] = seq->startdisp; - seq_frames[1] = seq->enddisp; + seq_frames[0] = SEQ_time_left_handle_frame_get(seq); + seq_frames[1] = SEQ_time_right_handle_frame_get(seq); seq_frames_tot = 2; } @@ -431,11 +342,11 @@ void SEQ_timeline_expand_boundbox(const ListBase *seqbase, rctf *rect) } LISTBASE_FOREACH (Sequence *, seq, seqbase) { - if (rect->xmin > seq->startdisp - 1) { - rect->xmin = seq->startdisp - 1; + if (rect->xmin > SEQ_time_left_handle_frame_get(seq) - 1) { + rect->xmin = SEQ_time_left_handle_frame_get(seq) - 1; } - if (rect->xmax < seq->enddisp + 1) { - rect->xmax = seq->enddisp + 1; + if (rect->xmax < SEQ_time_right_handle_frame_get(seq) + 1) { + rect->xmax = SEQ_time_right_handle_frame_get(seq) + 1; } if (rect->ymax < seq->machine) { rect->ymax = seq->machine; @@ -507,7 +418,8 @@ void seq_time_gap_info_get(const Scene *scene, bool SEQ_time_strip_intersects_frame(const Sequence *seq, const int timeline_frame) { - return (seq->startdisp <= timeline_frame) && (seq->enddisp > timeline_frame); + return (SEQ_time_left_handle_frame_get(seq) <= timeline_frame) && + (SEQ_time_right_handle_frame_get(seq) > timeline_frame); } bool SEQ_time_has_left_still_frames(const Sequence *seq) @@ -525,21 +437,36 @@ bool SEQ_time_has_still_frames(const Sequence *seq) return SEQ_time_has_right_still_frames(seq) || SEQ_time_has_left_still_frames(seq); } -int SEQ_time_left_handle_frame_get(Sequence *seq) +int SEQ_time_left_handle_frame_get(const Sequence *seq) { + if (seq->seq1 || seq->seq2) { + return seq->startdisp; + } + return seq->start + seq->startofs; } -int SEQ_time_right_handle_frame_get(Sequence *seq) + +int SEQ_time_right_handle_frame_get(const Sequence *seq) { + if (seq->seq1 || seq->seq2) { + return seq->enddisp; + } + return seq->start + seq->len - seq->endofs; } -void SEQ_time_left_handle_frame_set(Sequence *seq, int val) +void SEQ_time_left_handle_frame_set(const Scene *scene, Sequence *seq, int val) { seq->startofs = val - seq->start; + seq->startdisp = val; /* 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)); } -void SEQ_time_right_handle_frame_set(Sequence *seq, int val) +void SEQ_time_right_handle_frame_set(const Scene *scene, Sequence *seq, int val) { seq->endofs = seq->start + seq->len - val; + seq->enddisp = val; /* 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)); } diff --git a/source/blender/sequencer/intern/strip_time.h b/source/blender/sequencer/intern/strip_time.h index c96a016e646..7a75aeac1a6 100644 --- a/source/blender/sequencer/intern/strip_time.h +++ b/source/blender/sequencer/intern/strip_time.h @@ -14,9 +14,10 @@ extern "C" { struct ListBase; struct Scene; struct Sequence; +struct SeqCollection; float seq_give_frame_index(struct Sequence *seq, float timeline_frame); -void seq_update_sound_bounds_recursive(struct Scene *scene, struct Sequence *metaseq); +void seq_update_sound_bounds_recursive(const struct Scene *scene, struct Sequence *metaseq); /* Describes gap between strips in timeline. */ typedef struct GapInfo { @@ -37,6 +38,8 @@ void seq_time_gap_info_get(const struct Scene *scene, struct ListBase *seqbase, int initial_frame, struct GapInfo *r_gap_info); +void seq_time_effect_range_set(Sequence *seq); +void seq_time_update_effects_strip_range(const struct Scene *scene, struct SeqCollection *effects); #ifdef __cplusplus } diff --git a/source/blender/sequencer/intern/strip_transform.c b/source/blender/sequencer/intern/strip_transform.c index 8ff577240d6..051dc3961ba 100644 --- a/source/blender/sequencer/intern/strip_transform.c +++ b/source/blender/sequencer/intern/strip_transform.c @@ -25,6 +25,9 @@ #include "SEQ_time.h" #include "SEQ_transform.h" +#include "strip_time.h" +#include "sequencer.h" + #include "CLG_log.h" static CLG_LogRef LOG = {"seq.strip_transform"}; @@ -86,16 +89,16 @@ bool SEQ_transform_seqbase_isolated_sel_check(ListBase *seqbase) return true; } -void SEQ_transform_handle_xlimits(Sequence *seq, int leftflag, int rightflag) +void SEQ_transform_handle_xlimits(const Scene *scene, Sequence *seq, int leftflag, int rightflag) { if (leftflag) { if (SEQ_time_left_handle_frame_get(seq) >= SEQ_time_right_handle_frame_get(seq)) { - SEQ_time_left_handle_frame_set(seq, SEQ_time_right_handle_frame_get(seq) - 1); + SEQ_time_left_handle_frame_set(scene, seq, SEQ_time_right_handle_frame_get(seq) - 1); } if (SEQ_transform_single_image_check(seq) == 0) { if (SEQ_time_left_handle_frame_get(seq) >= seq_tx_get_end(seq)) { - SEQ_time_left_handle_frame_set(seq, seq_tx_get_end(seq) - 1); + SEQ_time_left_handle_frame_set(scene, seq, seq_tx_get_end(seq) - 1); } /* TODO: This doesn't work at the moment. */ @@ -112,12 +115,12 @@ void SEQ_transform_handle_xlimits(Sequence *seq, int leftflag, int rightflag) if (rightflag) { if (SEQ_time_right_handle_frame_get(seq) <= SEQ_time_left_handle_frame_get(seq)) { - SEQ_time_right_handle_frame_set(seq, SEQ_time_left_handle_frame_get(seq) + 1); + SEQ_time_right_handle_frame_set(scene, seq, SEQ_time_left_handle_frame_get(seq) + 1); } if (SEQ_transform_single_image_check(seq) == 0) { if (SEQ_time_right_handle_frame_get(seq) <= seq_tx_get_start(seq)) { - SEQ_time_right_handle_frame_set(seq, seq_tx_get_start(seq) + 1); + SEQ_time_right_handle_frame_set(scene, seq, seq_tx_get_start(seq) + 1); } } } @@ -129,7 +132,7 @@ void SEQ_transform_handle_xlimits(Sequence *seq, int leftflag, int rightflag) } } -void SEQ_transform_fix_single_image_seq_offsets(Sequence *seq) +void SEQ_transform_fix_single_image_seq_offsets(const Scene *scene, Sequence *seq) { int left, start, offset; if (!SEQ_transform_single_image_check(seq)) { @@ -142,8 +145,8 @@ void SEQ_transform_fix_single_image_seq_offsets(Sequence *seq) start = seq->start; if (start != left) { offset = left - start; - SEQ_time_left_handle_frame_set(seq, SEQ_time_left_handle_frame_get(seq) - offset); - SEQ_time_right_handle_frame_set(seq, SEQ_time_right_handle_frame_get(seq) - offset); + SEQ_time_left_handle_frame_set(scene, seq, SEQ_time_left_handle_frame_get(seq) - offset); + SEQ_time_right_handle_frame_set(scene, seq, SEQ_time_right_handle_frame_get(seq) - offset); seq->start += offset; } } @@ -156,7 +159,8 @@ bool SEQ_transform_sequence_can_be_translated(Sequence *seq) bool SEQ_transform_test_overlap_seq_seq(Sequence *seq1, Sequence *seq2) { return (seq1 != seq2 && seq1->machine == seq2->machine && - ((seq1->enddisp <= seq2->startdisp) || (seq1->startdisp >= seq2->enddisp)) == 0); + ((SEQ_time_right_handle_frame_get(seq1) <= SEQ_time_left_handle_frame_get(seq2)) || + (SEQ_time_left_handle_frame_get(seq1) >= SEQ_time_right_handle_frame_get(seq2))) == 0); } bool SEQ_transform_test_overlap(ListBase *seqbasep, Sequence *test) @@ -180,9 +184,6 @@ void SEQ_transform_translate_sequence(Scene *evil_scene, Sequence *seq, int delt return; } - SEQ_offset_animdata(evil_scene, seq, delta); - seq->start += delta; - /* Meta strips requires special handling: their content is to be translated, and then frame range * of the meta is to be updated for the updated content. */ if (seq->type == SEQ_TYPE_META) { @@ -190,16 +191,21 @@ void SEQ_transform_translate_sequence(Scene *evil_scene, Sequence *seq, int delt for (seq_child = seq->seqbase.first; seq_child; seq_child = seq_child->next) { SEQ_transform_translate_sequence(evil_scene, seq_child, delta); } - /* Ensure that meta bounds are updated, but this function prevents resets seq->start and - * start/end point in timeline. */ - SEQ_time_update_meta_strip_range(evil_scene, seq); /* Move meta start/end points. */ - SEQ_time_left_handle_frame_set(seq, seq->startdisp + delta); - SEQ_time_right_handle_frame_set(seq, seq->enddisp + delta); + SEQ_time_left_handle_frame_set(evil_scene, seq, SEQ_time_left_handle_frame_get(seq) + delta); + SEQ_time_right_handle_frame_set(evil_scene, seq, SEQ_time_right_handle_frame_get(seq) + delta); + } + else { /* All other strip types. */ + seq->start += delta; + /* Only to make files usable in older versions. */ + seq->startdisp = SEQ_time_left_handle_frame_get(seq); + seq->enddisp = SEQ_time_right_handle_frame_get(seq); } - ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(evil_scene)); - SEQ_time_update_sequence(evil_scene, seqbase, seq); + 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)); } bool SEQ_transform_seqbase_shuffle_ex(ListBase *seqbasep, @@ -211,16 +217,12 @@ bool SEQ_transform_seqbase_shuffle_ex(ListBase *seqbasep, BLI_assert(ELEM(channel_delta, -1, 1)); test->machine += channel_delta; - SEQ_time_update_sequence(evil_scene, seqbasep, test); while (SEQ_transform_test_overlap(seqbasep, test)) { if ((channel_delta > 0) ? (test->machine >= MAXSEQ) : (test->machine < 1)) { break; } test->machine += channel_delta; - - /* XXX: I don't think this is needed since were only moving vertically, Campbell. */ - SEQ_time_update_sequence(evil_scene, seqbasep, test); } if (!SEQ_valid_strip_channel(test)) { @@ -228,19 +230,18 @@ bool SEQ_transform_seqbase_shuffle_ex(ListBase *seqbasep, * nicer to move it to the end */ Sequence *seq; - int new_frame = test->enddisp; + int new_frame = SEQ_time_right_handle_frame_get(test); for (seq = seqbasep->first; seq; seq = seq->next) { if (seq->machine == orig_machine) { - new_frame = max_ii(new_frame, seq->enddisp); + new_frame = max_ii(new_frame, SEQ_time_right_handle_frame_get(seq)); } } test->machine = orig_machine; - new_frame = new_frame + (test->start - test->startdisp); /* adjust by the startdisp */ + new_frame = new_frame + + (test->start - SEQ_time_left_handle_frame_get(test)); /* adjust by the startdisp */ SEQ_transform_translate_sequence(evil_scene, test, new_frame - test->start); - - SEQ_time_update_sequence(evil_scene, seqbasep, test); return false; } @@ -252,61 +253,57 @@ bool SEQ_transform_seqbase_shuffle(ListBase *seqbasep, Sequence *test, Scene *ev return SEQ_transform_seqbase_shuffle_ex(seqbasep, test, evil_scene, 1); } -static int shuffle_seq_time_offset_test(SeqCollection *strips_to_shuffle, - ListBase *seqbasep, - char dir) +static bool shuffle_seq_test_overlap(const Sequence *seq1, const Sequence *seq2, const int offset) { - int offset = 0; - Sequence *seq; - - SEQ_ITERATOR_FOREACH (seq, strips_to_shuffle) { - LISTBASE_FOREACH (Sequence *, seq_other, seqbasep) { - if (!SEQ_transform_test_overlap_seq_seq(seq, seq_other)) { - continue; - } - if (SEQ_relation_is_effect_of_strip(seq_other, seq)) { - continue; - } - if (UNLIKELY(SEQ_collection_has_strip(seq_other, strips_to_shuffle))) { - CLOG_WARN(&LOG, - "Strip overlaps with itself or another strip, that is to be shuffled. " - "This should never happen."); - continue; - } - if (dir == 'L') { - offset = min_ii(offset, seq_other->startdisp - seq->enddisp); - } - else { - offset = max_ii(offset, seq_other->enddisp - seq->startdisp); - } - } - } - return offset; + return ( + seq1 != seq2 && seq1->machine == seq2->machine && + ((SEQ_time_right_handle_frame_get(seq1) + offset <= SEQ_time_left_handle_frame_get(seq2)) || + (SEQ_time_left_handle_frame_get(seq1) + offset >= SEQ_time_right_handle_frame_get(seq2))) == + 0); } -static int shuffle_seq_time_offset(SeqCollection *strips_to_shuffle, - ListBase *seqbasep, - Scene *scene, - char dir) +static int shuffle_seq_time_offset_get(SeqCollection *strips_to_shuffle, + ListBase *seqbasep, + char dir) { - int ofs = 0; - int tot_ofs = 0; + int offset = 0; Sequence *seq; - while ((ofs = shuffle_seq_time_offset_test(strips_to_shuffle, seqbasep, dir))) { + bool all_conflicts_resolved = false; + + while (!all_conflicts_resolved) { + all_conflicts_resolved = true; SEQ_ITERATOR_FOREACH (seq, strips_to_shuffle) { - /* seq_test_overlap only tests display values */ - seq->startdisp += ofs; - seq->enddisp += ofs; - } + LISTBASE_FOREACH (Sequence *, seq_other, seqbasep) { + if (!shuffle_seq_test_overlap(seq, seq_other, offset)) { + continue; + } + if (SEQ_relation_is_effect_of_strip(seq_other, seq)) { + continue; + } + if (UNLIKELY(SEQ_collection_has_strip(seq_other, strips_to_shuffle))) { + CLOG_WARN(&LOG, + "Strip overlaps with itself or another strip, that is to be shuffled. " + "This should never happen."); + continue; + } - tot_ofs += ofs; - } + all_conflicts_resolved = false; - SEQ_ITERATOR_FOREACH (seq, strips_to_shuffle) { - SEQ_time_update_sequence(scene, seqbasep, seq); /* corrects dummy startdisp/enddisp values */ + if (dir == 'L') { + offset = min_ii(offset, + SEQ_time_left_handle_frame_get(seq_other) - + SEQ_time_right_handle_frame_get(seq)); + } + else { + offset = max_ii(offset, + SEQ_time_right_handle_frame_get(seq_other) - + SEQ_time_left_handle_frame_get(seq)); + } + } + } } - return tot_ofs; + return offset; } bool SEQ_transform_seqbase_shuffle_time(SeqCollection *strips_to_shuffle, @@ -315,8 +312,8 @@ bool SEQ_transform_seqbase_shuffle_time(SeqCollection *strips_to_shuffle, ListBase *markers, const bool use_sync_markers) { - int offset_l = shuffle_seq_time_offset(strips_to_shuffle, seqbasep, evil_scene, 'L'); - int offset_r = shuffle_seq_time_offset(strips_to_shuffle, seqbasep, evil_scene, 'R'); + int offset_l = shuffle_seq_time_offset_get(strips_to_shuffle, seqbasep, 'L'); + int offset_r = shuffle_seq_time_offset_get(strips_to_shuffle, seqbasep, 'R'); int offset = (-offset_l < offset_r) ? offset_l : offset_r; if (offset) { @@ -346,9 +343,8 @@ void SEQ_transform_offset_after_frame(Scene *scene, const int timeline_frame) { LISTBASE_FOREACH (Sequence *, seq, seqbase) { - if (seq->startdisp >= timeline_frame) { + if (SEQ_time_left_handle_frame_get(seq) >= timeline_frame) { SEQ_transform_translate_sequence(scene, seq, delta); - SEQ_time_update_sequence(scene, seqbase, seq); SEQ_relations_invalidate_cache_preprocessed(scene, seq); } } diff --git a/source/blender/sequencer/intern/utils.c b/source/blender/sequencer/intern/utils.c index 0cf47420d8f..260f82310fb 100644 --- a/source/blender/sequencer/intern/utils.c +++ b/source/blender/sequencer/intern/utils.c @@ -39,55 +39,9 @@ #include "multiview.h" #include "proxy.h" +#include "sequencer.h" #include "utils.h" -void SEQ_sort(ListBase *seqbase) -{ - if (seqbase == NULL) { - return; - } - - /* all strips together per kind, and in order of y location ("machine") */ - ListBase inputbase, effbase; - Sequence *seq, *seqt; - - BLI_listbase_clear(&inputbase); - BLI_listbase_clear(&effbase); - - while ((seq = BLI_pophead(seqbase))) { - - if (seq->type & SEQ_TYPE_EFFECT) { - seqt = effbase.first; - while (seqt) { - if (seqt->machine >= seq->machine) { - BLI_insertlinkbefore(&effbase, seqt, seq); - break; - } - seqt = seqt->next; - } - if (seqt == NULL) { - BLI_addtail(&effbase, seq); - } - } - else { - seqt = inputbase.first; - while (seqt) { - if (seqt->machine >= seq->machine) { - BLI_insertlinkbefore(&inputbase, seqt, seq); - break; - } - seqt = seqt->next; - } - if (seqt == NULL) { - BLI_addtail(&inputbase, seq); - } - } - } - - BLI_movelisttolist(seqbase, &inputbase); - BLI_movelisttolist(seqbase, &effbase); -} - typedef struct SeqUniqueInfo { Sequence *seq; char name_src[SEQ_NAME_MAXSTR]; @@ -414,20 +368,18 @@ const Sequence *SEQ_get_topmost_sequence(const Scene *scene, int frame) return best_seq; } -ListBase *SEQ_get_seqbase_by_seq(ListBase *seqbase, Sequence *seq) +ListBase *SEQ_get_seqbase_by_seq(const Scene *scene, Sequence *seq) { - Sequence *iseq; - ListBase *lb = NULL; + Editing *ed = SEQ_editing_get(scene); + ListBase *main_seqbase = &ed->seqbase; + Sequence *seq_meta = seq_sequence_lookup_meta_by_seq(scene, seq); - for (iseq = seqbase->first; iseq; iseq = iseq->next) { - if (seq == iseq) { - return seqbase; - } - if (iseq->seqbase.first && (lb = SEQ_get_seqbase_by_seq(&iseq->seqbase, seq))) { - return lb; - } + if (seq_meta != NULL) { + return &seq_meta->seqbase; + } + if (BLI_findindex(main_seqbase, seq) >= 0) { + return main_seqbase; } - return NULL; } |