diff options
Diffstat (limited to 'source/blender/sequencer/intern/sequencer.c')
-rw-r--r-- | source/blender/sequencer/intern/sequencer.c | 2998 |
1 files changed, 135 insertions, 2863 deletions
diff --git a/source/blender/sequencer/intern/sequencer.c b/source/blender/sequencer/intern/sequencer.c index 67b3b9f5fbd..155c35c2491 100644 --- a/source/blender/sequencer/intern/sequencer.c +++ b/source/blender/sequencer/intern/sequencer.c @@ -24,131 +24,52 @@ * \ingroup bke */ -#include <math.h> -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> - #include "MEM_guardedalloc.h" #include "DNA_anim_types.h" -#include "DNA_mask_types.h" -#include "DNA_movieclip_types.h" -#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_sequence_types.h" -#include "DNA_sound_types.h" -#include "DNA_space_types.h" -#include "DNA_windowmanager_types.h" -#include "BLI_fileops.h" -#include "BLI_linklist.h" #include "BLI_listbase.h" -#include "BLI_math.h" -#include "BLI_path_util.h" -#include "BLI_session_uuid.h" #include "BLI_string.h" -#include "BLI_string_utf8.h" -#include "BLI_threads.h" -#include "BLI_utildefines.h" - -#ifdef WIN32 -# include "BLI_winstuff.h" -#else -# include <unistd.h> -#endif - -#include "BLT_translation.h" -#include "BKE_anim_data.h" #include "BKE_animsys.h" #include "BKE_fcurve.h" -#include "BKE_global.h" #include "BKE_idprop.h" -#include "BKE_image.h" -#include "BKE_layer.h" #include "BKE_lib_id.h" -#include "BKE_main.h" -#include "BKE_mask.h" -#include "BKE_movieclip.h" -#include "BKE_report.h" -#include "BKE_scene.h" -#include "BKE_sequencer_offscreen.h" +#include "BKE_sound.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" - -#include "RNA_access.h" - -#include "RE_pipeline.h" - -#include "SEQ_sequencer.h" - -#include <pthread.h> #include "IMB_colormanagement.h" #include "IMB_imbuf.h" -#include "IMB_imbuf_types.h" -#include "IMB_metadata.h" - -#include "BKE_context.h" -#include "BKE_sound.h" -#include "RE_engine.h" +#include "SEQ_sequencer.h" +#include "image_cache.h" +#include "prefetch.h" #include "sequencer.h" - -#ifdef WITH_AUDASPACE -# include <AUD_Special.h> -#endif +#include "utils.h" static void seq_free_animdata(Scene *scene, Sequence *seq); -static void seq_anim_add_suffix(Scene *scene, struct anim *anim, const int view_id); - -/* **** XXX ******** */ -#define SELECT 1 -ListBase seqbase_clipboard; -int seqbase_clipboard_frame; -int BKE_sequencer_base_recursive_apply(ListBase *seqbase, - int (*apply_fn)(Sequence *seq, void *), - void *arg) -{ - Sequence *iseq; - for (iseq = seqbase->first; iseq; iseq = iseq->next) { - if (BKE_sequencer_recursive_apply(iseq, apply_fn, arg) == -1) { - return -1; /* bail out */ - } - } - return 1; -} +/* -------------------------------------------------------------------- */ +/** \name Alloc / free functions + * \{ */ -int BKE_sequencer_recursive_apply(Sequence *seq, int (*apply_fn)(Sequence *, void *), void *arg) +static Strip *seq_strip_alloc(int type) { - int ret = apply_fn(seq, arg); - - if (ret == -1) { - return -1; /* bail out */ - } + Strip *strip = MEM_callocN(sizeof(Strip), "strip"); - if (ret && seq->seqbase.first) { - ret = BKE_sequencer_base_recursive_apply(&seq->seqbase, apply_fn, arg); + if (ELEM(type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD) == 0) { + strip->transform = MEM_callocN(sizeof(struct StripTransform), "StripTransform"); + strip->transform->scale_x = 1; + strip->transform->scale_y = 1; + strip->crop = MEM_callocN(sizeof(struct StripCrop), "StripCrop"); } - return ret; -} - -/*********************** alloc / free functions *************************/ - -/* free */ - -static void free_proxy_seq(Sequence *seq) -{ - if (seq->strip && seq->strip->proxy && seq->strip->proxy->anim) { - IMB_free_anim(seq->strip->proxy->anim); - seq->strip->proxy->anim = NULL; - } + strip->us = 1; + return strip; } static void seq_free_strip(Strip *strip) @@ -183,6 +104,36 @@ static void seq_free_strip(Strip *strip) MEM_freeN(strip); } +Sequence *BKE_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int type) +{ + Sequence *seq; + + seq = MEM_callocN(sizeof(Sequence), "addseq"); + BLI_addtail(lb, seq); + + *((short *)seq->name) = ID_SEQ; + seq->name[2] = 0; + + seq->flag = SELECT; + seq->start = timeline_frame; + seq->machine = machine; + seq->sat = 1.0; + seq->mul = 1.0; + seq->blend_opacity = 100.0; + seq->volume = 1.0f; + seq->pitch = 1.0f; + seq->scene_sound = NULL; + seq->type = type; + + seq->strip = seq_strip_alloc(type); + seq->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Sequence Stereo Format"); + seq->cache_flag = SEQ_CACHE_STORE_RAW | SEQ_CACHE_STORE_PREPROCESSED | SEQ_CACHE_STORE_COMPOSITE; + + BKE_sequence_session_uuid_generate(seq); + + return seq; +} + /* only give option to skip cache locally (static func) */ static void BKE_sequence_free_ex(Scene *scene, Sequence *seq, @@ -259,22 +210,6 @@ void BKE_sequence_free(Scene *scene, Sequence *seq, const bool do_clean_animdata BKE_sequence_free_ex(scene, seq, true, true, do_clean_animdata); } -/* Function to free imbuf and anim data on changes */ -void BKE_sequence_free_anim(Sequence *seq) -{ - while (seq->anims.last) { - StripAnim *sanim = seq->anims.last; - - if (sanim->anim) { - IMB_free_anim(sanim->anim); - sanim->anim = NULL; - } - - BLI_freelinkN(&seq->anims, sanim); - } - BLI_listbase_clear(&seq->anims); -} - /* cache must be freed before calling this function * since it leaves the seqbase in an invalid state */ void seq_free_sequence_recurse(Scene *scene, Sequence *seq, const bool do_id_user) @@ -297,135 +232,6 @@ Editing *BKE_sequencer_editing_get(Scene *scene, bool alloc) return scene->ed; } -void BKE_sequencer_free_clipboard(void) -{ - Sequence *seq, *nseq; - - BKE_sequencer_base_clipboard_pointers_free(&seqbase_clipboard); - - for (seq = seqbase_clipboard.first; seq; seq = nseq) { - nseq = seq->next; - seq_free_sequence_recurse(NULL, seq, false); - } - BLI_listbase_clear(&seqbase_clipboard); -} - -/* -------------------------------------------------------------------- */ -/* Manage pointers in the clipboard. - * note that these pointers should _never_ be access in the sequencer, - * they are only for storage while in the clipboard - * notice 'newid' is used for temp pointer storage here, validate on access (this is safe usage, - * since those data-blocks are fully out of Main lists). - */ -#define ID_PT (*id_pt) -static void seqclipboard_ptr_free(Main *UNUSED(bmain), ID **id_pt) -{ - if (ID_PT) { - BLI_assert(ID_PT->newid != NULL); - MEM_freeN(ID_PT); - ID_PT = NULL; - } -} -static void seqclipboard_ptr_store(Main *UNUSED(bmain), ID **id_pt) -{ - if (ID_PT) { - ID *id_prev = ID_PT; - ID_PT = MEM_dupallocN(ID_PT); - ID_PT->newid = id_prev; - } -} -static void seqclipboard_ptr_restore(Main *bmain, ID **id_pt) -{ - if (ID_PT) { - const ListBase *lb = which_libbase(bmain, GS(ID_PT->name)); - void *id_restore; - - BLI_assert(ID_PT->newid != NULL); - if (BLI_findindex(lb, (ID_PT)->newid) != -1) { - /* the pointer is still valid */ - id_restore = (ID_PT)->newid; - } - else { - /* the pointer of the same name still exists */ - id_restore = BLI_findstring(lb, (ID_PT)->name + 2, offsetof(ID, name) + 2); - } - - if (id_restore == NULL) { - /* check for a data with the same filename */ - switch (GS(ID_PT->name)) { - case ID_SO: { - id_restore = BLI_findstring(lb, ((bSound *)ID_PT)->filepath, offsetof(bSound, filepath)); - if (id_restore == NULL) { - id_restore = BKE_sound_new_file(bmain, ((bSound *)ID_PT)->filepath); - (ID_PT)->newid = id_restore; /* reuse next time */ - } - break; - } - case ID_MC: { - id_restore = BLI_findstring( - lb, ((MovieClip *)ID_PT)->filepath, offsetof(MovieClip, filepath)); - if (id_restore == NULL) { - id_restore = BKE_movieclip_file_add(bmain, ((MovieClip *)ID_PT)->filepath); - (ID_PT)->newid = id_restore; /* reuse next time */ - } - break; - } - default: - break; - } - } - - /* Replace with pointer to actual data-block. */ - seqclipboard_ptr_free(bmain, id_pt); - ID_PT = id_restore; - } -} -#undef ID_PT - -static void sequence_clipboard_pointers(Main *bmain, - Sequence *seq, - void (*callback)(Main *, ID **)) -{ - callback(bmain, (ID **)&seq->scene); - callback(bmain, (ID **)&seq->scene_camera); - callback(bmain, (ID **)&seq->clip); - callback(bmain, (ID **)&seq->mask); - callback(bmain, (ID **)&seq->sound); - - if (seq->type == SEQ_TYPE_TEXT && seq->effectdata) { - TextVars *text_data = seq->effectdata; - callback(bmain, (ID **)&text_data->text_font); - } -} - -/* recursive versions of functions above */ -void BKE_sequencer_base_clipboard_pointers_free(ListBase *seqbase) -{ - Sequence *seq; - for (seq = seqbase->first; seq; seq = seq->next) { - sequence_clipboard_pointers(NULL, seq, seqclipboard_ptr_free); - BKE_sequencer_base_clipboard_pointers_free(&seq->seqbase); - } -} -void BKE_sequencer_base_clipboard_pointers_store(Main *bmain, ListBase *seqbase) -{ - Sequence *seq; - for (seq = seqbase->first; seq; seq = seq->next) { - sequence_clipboard_pointers(bmain, seq, seqclipboard_ptr_store); - BKE_sequencer_base_clipboard_pointers_store(bmain, &seq->seqbase); - } -} -void BKE_sequencer_base_clipboard_pointers_restore(ListBase *seqbase, Main *bmain) -{ - Sequence *seq; - for (seq = seqbase->first; seq; seq = seq->next) { - sequence_clipboard_pointers(bmain, seq, seqclipboard_ptr_restore); - BKE_sequencer_base_clipboard_pointers_restore(&seq->seqbase, bmain); - } -} - -/* end clipboard pointer mess */ - Editing *BKE_sequencer_editing_ensure(Scene *scene) { if (scene->ed == NULL) { @@ -467,2362 +273,39 @@ void BKE_sequencer_editing_free(Scene *scene, const bool do_id_user) scene->ed = NULL; } -/* ************************* iterator ************************** */ -/* *************** (replaces old WHILE_SEQ) ********************* */ -/* **************** use now SEQ_ALL_BEGIN () SEQ_ALL_END ***************** */ - -/* sequence strip iterator: - * - builds a full array, recursively into meta strips - */ - -static void seq_count(ListBase *seqbase, int *tot) -{ - Sequence *seq; - - for (seq = seqbase->first; seq; seq = seq->next) { - (*tot)++; - - if (seq->seqbase.first) { - seq_count(&seq->seqbase, tot); - } - } -} - -static void seq_build_array(ListBase *seqbase, Sequence ***array, int depth) -{ - Sequence *seq; - - for (seq = seqbase->first; seq; seq = seq->next) { - seq->depth = depth; - - if (seq->seqbase.first) { - seq_build_array(&seq->seqbase, array, depth + 1); - } - - **array = seq; - (*array)++; - } -} - -static void seq_array(Editing *ed, - Sequence ***seqarray, - int *tot, - const bool use_current_sequences) -{ - Sequence **array; - - *seqarray = NULL; - *tot = 0; - - if (ed == NULL) { - return; - } - - if (use_current_sequences) { - seq_count(ed->seqbasep, tot); - } - else { - seq_count(&ed->seqbase, tot); - } - - if (*tot == 0) { - return; - } - - *seqarray = array = MEM_mallocN(sizeof(Sequence *) * (*tot), "SeqArray"); - if (use_current_sequences) { - seq_build_array(ed->seqbasep, &array, 0); - } - else { - seq_build_array(&ed->seqbase, &array, 0); - } -} - -void BKE_sequence_iterator_begin(Editing *ed, SeqIterator *iter, const bool use_current_sequences) -{ - memset(iter, 0, sizeof(*iter)); - seq_array(ed, &iter->array, &iter->tot, use_current_sequences); - - if (iter->tot) { - iter->cur = 0; - iter->seq = iter->array[iter->cur]; - iter->valid = 1; - } -} - -void BKE_sequence_iterator_next(SeqIterator *iter) -{ - if (++iter->cur < iter->tot) { - iter->seq = iter->array[iter->cur]; - } - else { - iter->valid = 0; - } -} - -void BKE_sequence_iterator_end(SeqIterator *iter) -{ - if (iter->array) { - MEM_freeN(iter->array); - } - - iter->valid = 0; -} - -static int metaseq_start(Sequence *metaseq) -{ - return metaseq->start + metaseq->startofs; -} - -static int metaseq_end(Sequence *metaseq) -{ - return metaseq->start + metaseq->len - metaseq->endofs; -} - -static void seq_update_sound_bounds_recursive_impl(Scene *scene, - Sequence *metaseq, - int start, - int end) -{ - Sequence *seq; - - /* for sound we go over full meta tree to update bounds of the sound strips, - * since sound is played outside of evaluating the imbufs, */ - for (seq = metaseq->seqbase.first; seq; seq = seq->next) { - if (seq->type == SEQ_TYPE_META) { - seq_update_sound_bounds_recursive_impl( - scene, seq, max_ii(start, metaseq_start(seq)), min_ii(end, metaseq_end(seq))); - } - else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) { - if (seq->scene_sound) { - int startofs = seq->startofs; - int endofs = seq->endofs; - if (seq->startofs + seq->start < start) { - startofs = start - seq->start; - } - - if (seq->start + seq->len - seq->endofs > end) { - endofs = seq->start + seq->len - end; - } - - BKE_sound_move_scene_sound(scene, - seq->scene_sound, - seq->start + startofs, - seq->start + seq->len - endofs, - startofs + seq->anim_startofs); - } - } - } -} - -static void seq_update_sound_bounds_recursive(Scene *scene, Sequence *metaseq) -{ - seq_update_sound_bounds_recursive_impl( - scene, metaseq, metaseq_start(metaseq), metaseq_end(metaseq)); -} - -void BKE_sequence_calc_disp(Scene *scene, Sequence *seq) -{ - if (seq->startofs && seq->startstill) { - seq->startstill = 0; - } - if (seq->endofs && seq->endstill) { - seq->endstill = 0; - } - - seq->startdisp = seq->start + seq->startofs - seq->startstill; - seq->enddisp = seq->start + seq->len - seq->endofs + seq->endstill; - - if (seq->type == SEQ_TYPE_META) { - seq_update_sound_bounds_recursive(scene, seq); - } -} - -void BKE_sequence_calc(Scene *scene, Sequence *seq) +static void seq_new_fix_links_recursive(Sequence *seq) { - Sequence *seqm; - int min, max; - - /* check all metas recursively */ - seqm = seq->seqbase.first; - while (seqm) { - if (seqm->seqbase.first) { - BKE_sequence_calc(scene, seqm); - } - seqm = seqm->next; - } + SequenceModifierData *smd; - /* effects and meta: automatic start and end */ if (seq->type & SEQ_TYPE_EFFECT) { - if (seq->seq1) { - seq->startofs = seq->endofs = seq->startstill = seq->endstill = 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 cant help if strips don't overlap, it wont 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 { - BKE_sequence_calc_disp(scene, seq); - } - } - else { - if (seq->type == SEQ_TYPE_META) { - seqm = seq->seqbase.first; - if (seqm) { - min = MAXFRAME * 2; - max = -MAXFRAME * 2; - while (seqm) { - if (seqm->startdisp < min) { - min = seqm->startdisp; - } - if (seqm->enddisp > max) { - max = seqm->enddisp; - } - seqm = seqm->next; - } - seq->start = min + seq->anim_startofs; - seq->len = max - min; - seq->len -= seq->anim_startofs; - seq->len -= seq->anim_endofs; - } - seq_update_sound_bounds_recursive(scene, seq); - } - BKE_sequence_calc_disp(scene, seq); - } -} - -void seq_multiview_name(Scene *scene, - const int view_id, - const char *prefix, - const char *ext, - char *r_path, - size_t r_size) -{ - const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, view_id); - BLI_assert(ext != NULL && suffix != NULL && prefix != NULL); - BLI_snprintf(r_path, r_size, "%s%s%s", prefix, suffix, ext); -} - -/* note: caller should run BKE_sequence_calc(scene, seq) after */ -void BKE_sequence_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, const bool lock_range) -{ - char path[FILE_MAX]; - int prev_startdisp = 0, prev_enddisp = 0; - /* note: don't rename the strip, will break animation curves */ - - if (ELEM(seq->type, - SEQ_TYPE_MOVIE, - SEQ_TYPE_IMAGE, - SEQ_TYPE_SOUND_RAM, - SEQ_TYPE_SCENE, - SEQ_TYPE_META, - SEQ_TYPE_MOVIECLIP, - SEQ_TYPE_MASK) == 0) { - return; - } - - if (lock_range) { - /* keep so we don't have to move the actual start and end points (only the data) */ - BKE_sequence_calc_disp(scene, seq); - prev_startdisp = seq->startdisp; - prev_enddisp = seq->enddisp; - } - - switch (seq->type) { - case SEQ_TYPE_IMAGE: { - /* Hack? */ - size_t olen = MEM_allocN_len(seq->strip->stripdata) / sizeof(StripElem); - - seq->len = olen; - seq->len -= seq->anim_startofs; - seq->len -= seq->anim_endofs; - if (seq->len < 0) { - seq->len = 0; - } - break; - } - case SEQ_TYPE_MOVIE: { - StripAnim *sanim; - bool is_multiview_loaded = false; - const bool is_multiview = (seq->flag & SEQ_USE_VIEWS) != 0 && - (scene->r.scemode & R_MULTIVIEW) != 0; - - BLI_join_dirfile(path, sizeof(path), seq->strip->dir, seq->strip->stripdata->name); - BLI_path_abs(path, BKE_main_blendfile_path_from_global()); - - BKE_sequence_free_anim(seq); - - if (is_multiview && (seq->views_format == R_IMF_VIEWS_INDIVIDUAL)) { - char prefix[FILE_MAX]; - const char *ext = NULL; - const int totfiles = seq_num_files(scene, seq->views_format, true); - int i = 0; - - BKE_scene_multiview_view_prefix_get(scene, path, prefix, &ext); - - if (prefix[0] != '\0') { - for (i = 0; i < totfiles; i++) { - struct anim *anim; - char str[FILE_MAX]; - - seq_multiview_name(scene, i, prefix, ext, str, FILE_MAX); - anim = openanim(str, - IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), - seq->streamindex, - seq->strip->colorspace_settings.name); - - if (anim) { - seq_anim_add_suffix(scene, anim, i); - sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim"); - BLI_addtail(&seq->anims, sanim); - sanim->anim = anim; - } - } - is_multiview_loaded = true; - } - } - - if (is_multiview_loaded == false) { - struct anim *anim; - anim = openanim(path, - IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), - seq->streamindex, - seq->strip->colorspace_settings.name); - if (anim) { - sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim"); - BLI_addtail(&seq->anims, sanim); - sanim->anim = anim; - } - } - - /* use the first video as reference for everything */ - sanim = seq->anims.first; - - if ((!sanim) || (!sanim->anim)) { - return; - } - - IMB_anim_load_metadata(sanim->anim); - - seq->len = IMB_anim_get_duration( - sanim->anim, seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN); - - seq->anim_preseek = IMB_anim_get_preseek(sanim->anim); - - seq->len -= seq->anim_startofs; - seq->len -= seq->anim_endofs; - if (seq->len < 0) { - seq->len = 0; - } - break; - } - case SEQ_TYPE_MOVIECLIP: - if (seq->clip == NULL) { - return; - } - - seq->len = BKE_movieclip_get_duration(seq->clip); - - seq->len -= seq->anim_startofs; - seq->len -= seq->anim_endofs; - if (seq->len < 0) { - seq->len = 0; - } - break; - case SEQ_TYPE_MASK: - if (seq->mask == NULL) { - return; - } - seq->len = BKE_mask_get_duration(seq->mask); - seq->len -= seq->anim_startofs; - seq->len -= seq->anim_endofs; - if (seq->len < 0) { - seq->len = 0; - } - break; - case SEQ_TYPE_SOUND_RAM: -#ifdef WITH_AUDASPACE - if (!seq->sound) { - return; - } - seq->len = ceil((double)BKE_sound_get_length(bmain, seq->sound) * FPS); - seq->len -= seq->anim_startofs; - seq->len -= seq->anim_endofs; - if (seq->len < 0) { - seq->len = 0; - } -#else - UNUSED_VARS(bmain); - return; -#endif - break; - case SEQ_TYPE_SCENE: { - seq->len = (seq->scene) ? seq->scene->r.efra - seq->scene->r.sfra + 1 : 0; - seq->len -= seq->anim_startofs; - seq->len -= seq->anim_endofs; - if (seq->len < 0) { - seq->len = 0; - } - break; - } - } - - free_proxy_seq(seq); - - if (lock_range) { - BKE_sequence_tx_set_final_left(seq, prev_startdisp); - BKE_sequence_tx_set_final_right(seq, prev_enddisp); - BKE_sequence_single_fix(seq); - } - - BKE_sequence_calc(scene, seq); -} - -void BKE_sequence_movie_reload_if_needed(struct Main *bmain, - struct Scene *scene, - struct Sequence *seq, - bool *r_was_reloaded, - bool *r_can_produce_frames) -{ - BLI_assert(seq->type == SEQ_TYPE_MOVIE || - !"This function is only implemented for movie strips."); - - bool must_reload = false; - - /* The Sequence struct allows for multiple anim structs to be associated with one strip. This - * function will return true only if there is at least one 'anim' AND all anims can produce - * frames. */ - - if (BLI_listbase_is_empty(&seq->anims)) { - /* No anim present, so reloading is always necessary. */ - must_reload = true; - } - else { - LISTBASE_FOREACH (StripAnim *, sanim, &seq->anims) { - if (!IMB_anim_can_produce_frames(sanim->anim)) { - /* Anim cannot produce frames, try reloading. */ - must_reload = true; - break; - } - }; - } - - if (!must_reload) { - /* There are one or more anims, and all can produce frames. */ - *r_was_reloaded = false; - *r_can_produce_frames = true; - return; - } - - BKE_sequence_reload_new_file(bmain, scene, seq, true); - *r_was_reloaded = true; - - if (BLI_listbase_is_empty(&seq->anims)) { - /* No anims present after reloading => no frames can be produced. */ - *r_can_produce_frames = false; - return; - } - - /* Check if there are still anims that cannot produce frames. */ - LISTBASE_FOREACH (StripAnim *, sanim, &seq->anims) { - if (!IMB_anim_can_produce_frames(sanim->anim)) { - /* There still is an anim that cannot produce frames. */ - *r_can_produce_frames = false; - return; - } - }; - - /* There are one or more anims, and all can produce frames. */ - *r_can_produce_frames = true; -} - -void BKE_sequencer_sort(Scene *scene) -{ - /* all strips together per kind, and in order of y location ("machine") */ - ListBase seqbase, effbase; - Editing *ed = BKE_sequencer_editing_get(scene, false); - Sequence *seq, *seqt; - - if (ed == NULL) { - return; - } - - BLI_listbase_clear(&seqbase); - BLI_listbase_clear(&effbase); - - while ((seq = BLI_pophead(ed->seqbasep))) { - - 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 = seqbase.first; - while (seqt) { - if (seqt->machine >= seq->machine) { - BLI_insertlinkbefore(&seqbase, seqt, seq); - break; - } - seqt = seqt->next; - } - if (seqt == NULL) { - BLI_addtail(&seqbase, seq); - } - } - } - - BLI_movelisttolist(&seqbase, &effbase); - *(ed->seqbasep) = seqbase; -} - -/** Comparison function suitable to be used with BLI_listbase_sort()... */ -int BKE_sequencer_cmp_time_startdisp(const void *a, const void *b) -{ - const Sequence *seq_a = a; - const Sequence *seq_b = b; - - return (seq_a->startdisp > seq_b->startdisp); -} - -typedef struct SeqUniqueInfo { - Sequence *seq; - char name_src[SEQ_NAME_MAXSTR]; - char name_dest[SEQ_NAME_MAXSTR]; - int count; - int match; -} SeqUniqueInfo; - -static void seqbase_unique_name(ListBase *seqbasep, SeqUniqueInfo *sui) -{ - Sequence *seq; - for (seq = seqbasep->first; seq; seq = seq->next) { - if ((sui->seq != seq) && STREQ(sui->name_dest, seq->name + 2)) { - /* SEQ_NAME_MAXSTR -4 for the number, -1 for \0, - 2 for r_prefix */ - BLI_snprintf(sui->name_dest, - sizeof(sui->name_dest), - "%.*s.%03d", - SEQ_NAME_MAXSTR - 4 - 1 - 2, - sui->name_src, - sui->count++); - sui->match = 1; /* be sure to re-scan */ - } - } -} - -static int seqbase_unique_name_recursive_fn(Sequence *seq, void *arg_pt) -{ - if (seq->seqbase.first) { - seqbase_unique_name(&seq->seqbase, (SeqUniqueInfo *)arg_pt); - } - return 1; -} - -void BKE_sequence_base_unique_name_recursive(ListBase *seqbasep, Sequence *seq) -{ - SeqUniqueInfo sui; - char *dot; - sui.seq = seq; - BLI_strncpy(sui.name_src, seq->name + 2, sizeof(sui.name_src)); - BLI_strncpy(sui.name_dest, seq->name + 2, sizeof(sui.name_dest)); - - sui.count = 1; - sui.match = 1; /* assume the worst to start the loop */ - - /* Strip off the suffix */ - if ((dot = strrchr(sui.name_src, '.'))) { - *dot = '\0'; - dot++; - - if (*dot) { - sui.count = atoi(dot) + 1; - } - } - - while (sui.match) { - sui.match = 0; - seqbase_unique_name(seqbasep, &sui); - BKE_sequencer_base_recursive_apply(seqbasep, seqbase_unique_name_recursive_fn, &sui); - } - - BLI_strncpy(seq->name + 2, sui.name_dest, sizeof(seq->name) - 2); -} - -static const char *give_seqname_by_type(int type) -{ - switch (type) { - case SEQ_TYPE_META: - return "Meta"; - case SEQ_TYPE_IMAGE: - return "Image"; - case SEQ_TYPE_SCENE: - return "Scene"; - case SEQ_TYPE_MOVIE: - return "Movie"; - case SEQ_TYPE_MOVIECLIP: - return "Clip"; - case SEQ_TYPE_MASK: - return "Mask"; - case SEQ_TYPE_SOUND_RAM: - return "Audio"; - case SEQ_TYPE_CROSS: - return "Cross"; - case SEQ_TYPE_GAMCROSS: - return "Gamma Cross"; - case SEQ_TYPE_ADD: - return "Add"; - case SEQ_TYPE_SUB: - return "Sub"; - case SEQ_TYPE_MUL: - return "Mul"; - case SEQ_TYPE_ALPHAOVER: - return "Alpha Over"; - case SEQ_TYPE_ALPHAUNDER: - return "Alpha Under"; - case SEQ_TYPE_OVERDROP: - return "Over Drop"; - case SEQ_TYPE_COLORMIX: - return "Color Mix"; - case SEQ_TYPE_WIPE: - return "Wipe"; - case SEQ_TYPE_GLOW: - return "Glow"; - case SEQ_TYPE_TRANSFORM: - return "Transform"; - case SEQ_TYPE_COLOR: - return "Color"; - case SEQ_TYPE_MULTICAM: - return "Multicam"; - case SEQ_TYPE_ADJUSTMENT: - return "Adjustment"; - case SEQ_TYPE_SPEED: - return "Speed"; - case SEQ_TYPE_GAUSSIAN_BLUR: - return "Gaussian Blur"; - case SEQ_TYPE_TEXT: - return "Text"; - default: - return NULL; - } -} - -const char *BKE_sequence_give_name(Sequence *seq) -{ - const char *name = give_seqname_by_type(seq->type); - - if (!name) { - if (!(seq->type & SEQ_TYPE_EFFECT)) { - return seq->strip->dir; - } - - return "Effect"; - } - return name; -} - -ListBase *BKE_sequence_seqbase_get(Sequence *seq, int *r_offset) -{ - ListBase *seqbase = NULL; - - switch (seq->type) { - case SEQ_TYPE_META: { - seqbase = &seq->seqbase; - *r_offset = seq->start; - break; - } - case SEQ_TYPE_SCENE: { - if (seq->flag & SEQ_SCENE_STRIPS && seq->scene) { - Editing *ed = BKE_sequencer_editing_get(seq->scene, false); - if (ed) { - seqbase = &ed->seqbase; - *r_offset = seq->scene->r.sfra; - } - } - break; - } - } - - return seqbase; -} - -/* the number of files will vary according to the stereo format */ -int seq_num_files(Scene *scene, char views_format, const bool is_multiview) -{ - if (!is_multiview) { - return 1; - } - if (views_format == R_IMF_VIEWS_STEREO_3D) { - return 1; - } - /* R_IMF_VIEWS_INDIVIDUAL */ - - return BKE_scene_multiview_num_views_get(&scene->r); -} - -void seq_proxy_index_dir_set(struct anim *anim, const char *base_dir) -{ - char dir[FILE_MAX]; - char fname[FILE_MAXFILE]; - - IMB_anim_get_fname(anim, fname, FILE_MAXFILE); - BLI_strncpy(dir, base_dir, sizeof(dir)); - BLI_path_append(dir, sizeof(dir), fname); - IMB_anim_set_index_dir(anim, dir); -} - -void seq_open_anim_file(Scene *scene, Sequence *seq, bool openfile) -{ - char dir[FILE_MAX]; - char name[FILE_MAX]; - StripProxy *proxy; - bool use_proxy; - bool is_multiview_loaded = false; - Editing *ed = scene->ed; - const bool is_multiview = (seq->flag & SEQ_USE_VIEWS) != 0 && - (scene->r.scemode & R_MULTIVIEW) != 0; - - if ((seq->anims.first != NULL) && (((StripAnim *)seq->anims.first)->anim != NULL)) { - return; - } - - /* reset all the previously created anims */ - BKE_sequence_free_anim(seq); - - BLI_join_dirfile(name, sizeof(name), seq->strip->dir, seq->strip->stripdata->name); - BLI_path_abs(name, BKE_main_blendfile_path_from_global()); - - proxy = seq->strip->proxy; - - use_proxy = proxy && ((proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR) != 0 || - (ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE)); - - if (use_proxy) { - if (ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE) { - if (ed->proxy_dir[0] == 0) { - BLI_strncpy(dir, "//BL_proxy", sizeof(dir)); - } - else { - BLI_strncpy(dir, ed->proxy_dir, sizeof(dir)); - } - } - else { - BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); - } - BLI_path_abs(dir, BKE_main_blendfile_path_from_global()); - } - - if (is_multiview && seq->views_format == R_IMF_VIEWS_INDIVIDUAL) { - int totfiles = seq_num_files(scene, seq->views_format, true); - char prefix[FILE_MAX]; - const char *ext = NULL; - int i; - - BKE_scene_multiview_view_prefix_get(scene, name, prefix, &ext); - - if (prefix[0] != '\0') { - for (i = 0; i < totfiles; i++) { - const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, i); - char str[FILE_MAX]; - StripAnim *sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim"); - - BLI_addtail(&seq->anims, sanim); - - BLI_snprintf(str, sizeof(str), "%s%s%s", prefix, suffix, ext); - - if (openfile) { - sanim->anim = openanim(str, - IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), - seq->streamindex, - seq->strip->colorspace_settings.name); - } - else { - sanim->anim = openanim_noload(str, - IB_rect | - ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), - seq->streamindex, - seq->strip->colorspace_settings.name); - } - - if (sanim->anim) { - /* we already have the suffix */ - IMB_suffix_anim(sanim->anim, suffix); - } - else { - if (openfile) { - sanim->anim = openanim(name, - IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), - seq->streamindex, - seq->strip->colorspace_settings.name); - } - else { - sanim->anim = openanim_noload(name, - IB_rect | - ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), - seq->streamindex, - seq->strip->colorspace_settings.name); - } - - /* No individual view files - monoscopic, stereo 3d or EXR multi-view. */ - totfiles = 1; - } - - if (sanim->anim && use_proxy) { - seq_proxy_index_dir_set(sanim->anim, dir); - } - } - is_multiview_loaded = true; - } - } - - if (is_multiview_loaded == false) { - StripAnim *sanim; - - sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim"); - BLI_addtail(&seq->anims, sanim); - - if (openfile) { - sanim->anim = openanim(name, - IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), - seq->streamindex, - seq->strip->colorspace_settings.name); - } - else { - sanim->anim = openanim_noload(name, - IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), - seq->streamindex, - seq->strip->colorspace_settings.name); - } - - if (sanim->anim && use_proxy) { - seq_proxy_index_dir_set(sanim->anim, dir); - } - } -} - -/* check whether sequence cur depends on seq */ -static bool BKE_sequence_check_depend(Sequence *seq, Sequence *cur) -{ - if (cur->seq1 == seq || cur->seq2 == seq || cur->seq3 == seq) { - return true; - } - - /* sequences are not intersecting in time, assume no dependency exists between them */ - if (cur->enddisp < seq->startdisp || cur->startdisp > seq->enddisp) { - return false; - } - - /* checking sequence is below reference one, not dependent on it */ - if (cur->machine < seq->machine) { - return false; - } - - /* sequence is not blending with lower machines, no dependency here occurs - * check for non-effects only since effect could use lower machines as input - */ - if ((cur->type & SEQ_TYPE_EFFECT) == 0 && - ((cur->blend_mode == SEQ_BLEND_REPLACE) || - (cur->blend_mode == SEQ_TYPE_CROSS && cur->blend_opacity == 100.0f))) { - return false; - } - - return true; -} - -static void sequence_do_invalidate_dependent(Scene *scene, Sequence *seq, ListBase *seqbase) -{ - Sequence *cur; - - for (cur = seqbase->first; cur; cur = cur->next) { - if (cur == seq) { - continue; - } - - if (BKE_sequence_check_depend(seq, cur)) { - /* Effect must be invalidated completely if they depend on invalidated seq. */ - if ((cur->type & SEQ_TYPE_EFFECT) != 0) { - BKE_sequencer_cache_cleanup_sequence(scene, cur, seq, SEQ_CACHE_ALL_TYPES, false); - } - else { - /* In case of alpha over for example only invalidate composite image */ - BKE_sequencer_cache_cleanup_sequence( - scene, cur, seq, SEQ_CACHE_STORE_COMPOSITE | SEQ_CACHE_STORE_FINAL_OUT, false); - } - } - - if (cur->seqbase.first) { - sequence_do_invalidate_dependent(scene, seq, &cur->seqbase); - } - } -} - -static void sequence_invalidate_cache(Scene *scene, - Sequence *seq, - bool invalidate_self, - int invalidate_types) -{ - Editing *ed = scene->ed; - - if (invalidate_self) { - BKE_sequence_free_anim(seq); - BKE_sequencer_cache_cleanup_sequence(scene, seq, seq, invalidate_types, false); - } - - if (seq->effectdata && seq->type == SEQ_TYPE_SPEED) { - BKE_sequence_effect_speed_rebuild_map(scene, seq, true); - } - - sequence_do_invalidate_dependent(scene, seq, &ed->seqbase); - DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); - BKE_sequencer_prefetch_stop(scene); -} - -void BKE_sequence_invalidate_cache_in_range(Scene *scene, - Sequence *seq, - Sequence *range_mask, - int invalidate_types) -{ - BKE_sequencer_cache_cleanup_sequence(scene, seq, range_mask, invalidate_types, true); -} - -void BKE_sequence_invalidate_cache_raw(Scene *scene, Sequence *seq) -{ - sequence_invalidate_cache(scene, seq, true, SEQ_CACHE_ALL_TYPES); -} - -void BKE_sequence_invalidate_cache_preprocessed(Scene *scene, Sequence *seq) -{ - sequence_invalidate_cache(scene, - seq, - true, - SEQ_CACHE_STORE_PREPROCESSED | SEQ_CACHE_STORE_COMPOSITE | - SEQ_CACHE_STORE_FINAL_OUT); -} - -void BKE_sequence_invalidate_cache_composite(Scene *scene, Sequence *seq) -{ - if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) { - return; - } - - sequence_invalidate_cache( - scene, seq, true, SEQ_CACHE_STORE_COMPOSITE | SEQ_CACHE_STORE_FINAL_OUT); -} - -void BKE_sequence_invalidate_dependent(Scene *scene, Sequence *seq) -{ - if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) { - return; - } - - sequence_invalidate_cache( - scene, seq, false, SEQ_CACHE_STORE_COMPOSITE | SEQ_CACHE_STORE_FINAL_OUT); -} - -static void invalidate_scene_strips(Scene *scene, Scene *scene_target, ListBase *seqbase) -{ - for (Sequence *seq = seqbase->first; seq != NULL; seq = seq->next) { - if (seq->scene == scene_target) { - BKE_sequence_invalidate_cache_raw(scene, seq); - } - - if (seq->seqbase.first != NULL) { - invalidate_scene_strips(scene, scene_target, &seq->seqbase); - } - } -} - -void BKE_sequence_invalidate_scene_strips(Main *bmain, Scene *scene_target) -{ - for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) { - if (scene->ed != NULL) { - invalidate_scene_strips(scene, scene_target, &scene->ed->seqbase); - } - } -} - -static void invalidate_movieclip_strips(Scene *scene, MovieClip *clip_target, ListBase *seqbase) -{ - for (Sequence *seq = seqbase->first; seq != NULL; seq = seq->next) { - if (seq->clip == clip_target) { - BKE_sequence_invalidate_cache_raw(scene, seq); - } - - if (seq->seqbase.first != NULL) { - invalidate_movieclip_strips(scene, clip_target, &seq->seqbase); - } - } -} - -void BKE_sequence_invalidate_movieclip_strips(Main *bmain, MovieClip *clip_target) -{ - for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) { - if (scene->ed != NULL) { - invalidate_movieclip_strips(scene, clip_target, &scene->ed->seqbase); - } - } -} - -void BKE_sequencer_free_imbuf(Scene *scene, ListBase *seqbase, bool for_render) -{ - if (scene->ed == NULL) { - return; - } - - Sequence *seq; - - BKE_sequencer_cache_cleanup(scene); - BKE_sequencer_prefetch_stop(scene); - - for (seq = seqbase->first; seq; seq = seq->next) { - if (for_render && CFRA >= seq->startdisp && CFRA <= seq->enddisp) { - continue; - } - - if (seq->strip) { - if (seq->type == SEQ_TYPE_MOVIE) { - BKE_sequence_free_anim(seq); - } - if (seq->type == SEQ_TYPE_SPEED) { - BKE_sequence_effect_speed_rebuild_map(scene, seq, true); - } - } - if (seq->type == SEQ_TYPE_META) { - BKE_sequencer_free_imbuf(scene, &seq->seqbase, for_render); - } - if (seq->type == SEQ_TYPE_SCENE) { - /* FIXME: recurse downwards, - * but do recurse protection somehow! */ - } - } -} - -static bool update_changed_seq_recurs( - Scene *scene, Sequence *seq, Sequence *changed_seq, int len_change, int ibuf_change) -{ - Sequence *subseq; - bool free_imbuf = false; - - /* recurse downwards to see if this seq depends on the changed seq */ - - if (seq == NULL) { - return false; - } - - if (seq == changed_seq) { - free_imbuf = true; - } - - for (subseq = seq->seqbase.first; subseq; subseq = subseq->next) { - if (update_changed_seq_recurs(scene, subseq, changed_seq, len_change, ibuf_change)) { - free_imbuf = true; - } - } - - if (seq->seq1) { - if (update_changed_seq_recurs(scene, seq->seq1, changed_seq, len_change, ibuf_change)) { - free_imbuf = true; - } - } - if (seq->seq2 && (seq->seq2 != seq->seq1)) { - if (update_changed_seq_recurs(scene, seq->seq2, changed_seq, len_change, ibuf_change)) { - free_imbuf = true; - } - } - if (seq->seq3 && (seq->seq3 != seq->seq1) && (seq->seq3 != seq->seq2)) { - if (update_changed_seq_recurs(scene, seq->seq3, changed_seq, len_change, ibuf_change)) { - free_imbuf = true; - } - } - - if (free_imbuf) { - if (ibuf_change) { - if (seq->type == SEQ_TYPE_MOVIE) { - BKE_sequence_free_anim(seq); - } - else if (seq->type == SEQ_TYPE_SPEED) { - BKE_sequence_effect_speed_rebuild_map(scene, seq, true); - } - } - - if (len_change) { - BKE_sequence_calc(scene, seq); - } - } - - return free_imbuf; -} - -void BKE_sequencer_update_changed_seq_and_deps(Scene *scene, - Sequence *changed_seq, - int len_change, - int ibuf_change) -{ - Editing *ed = BKE_sequencer_editing_get(scene, false); - Sequence *seq; - - if (ed == NULL) { - return; - } - - for (seq = ed->seqbase.first; seq; seq = seq->next) { - update_changed_seq_recurs(scene, seq, changed_seq, len_change, ibuf_change); - } -} - -/* seq funcs's for transforming internally - * notice the difference between start/end and left/right. - * - * left and right are the bounds at which the sequence is rendered, - * start and end are from the start and fixed length of the sequence. - */ -static int seq_tx_get_start(Sequence *seq) -{ - return seq->start; -} -static int seq_tx_get_end(Sequence *seq) -{ - return seq->start + seq->len; -} - -int BKE_sequence_tx_get_final_left(Sequence *seq, bool metaclip) -{ - if (metaclip && seq->tmp) { - /* return the range clipped by the parents range */ - return max_ii(BKE_sequence_tx_get_final_left(seq, false), - BKE_sequence_tx_get_final_left((Sequence *)seq->tmp, true)); - } - - return (seq->start - seq->startstill) + seq->startofs; -} -int BKE_sequence_tx_get_final_right(Sequence *seq, bool metaclip) -{ - if (metaclip && seq->tmp) { - /* return the range clipped by the parents range */ - return min_ii(BKE_sequence_tx_get_final_right(seq, false), - BKE_sequence_tx_get_final_right((Sequence *)seq->tmp, true)); - } - - return ((seq->start + seq->len) + seq->endstill) - seq->endofs; -} - -void BKE_sequence_tx_set_final_left(Sequence *seq, int val) -{ - if (val < (seq)->start) { - seq->startstill = abs(val - (seq)->start); - seq->startofs = 0; - } - else { - seq->startofs = abs(val - (seq)->start); - seq->startstill = 0; - } -} - -void BKE_sequence_tx_set_final_right(Sequence *seq, int val) -{ - if (val > (seq)->start + (seq)->len) { - seq->endstill = abs(val - (seq->start + (seq)->len)); - seq->endofs = 0; - } - else { - seq->endofs = abs(val - ((seq)->start + (seq)->len)); - seq->endstill = 0; - } -} - -/* used so we can do a quick check for single image seq - * since they work a bit differently to normal image seq's (during transform) */ -bool BKE_sequence_single_check(Sequence *seq) -{ - return ((seq->len == 1) && - (seq->type == SEQ_TYPE_IMAGE || - ((seq->type & SEQ_TYPE_EFFECT) && BKE_sequence_effect_get_num_inputs(seq->type) == 0))); -} - -/* check if the selected seq's reference unselected seq's */ -bool BKE_sequence_base_isolated_sel_check(ListBase *seqbase) -{ - Sequence *seq; - /* is there more than 1 select */ - bool ok = false; - - for (seq = seqbase->first; seq; seq = seq->next) { - if (seq->flag & SELECT) { - ok = true; - break; - } - } - - if (ok == false) { - return false; - } - - /* test relationships */ - for (seq = seqbase->first; seq; seq = seq->next) { - if ((seq->type & SEQ_TYPE_EFFECT) == 0) { - continue; - } - - if (seq->flag & SELECT) { - if ((seq->seq1 && (seq->seq1->flag & SELECT) == 0) || - (seq->seq2 && (seq->seq2->flag & SELECT) == 0) || - (seq->seq3 && (seq->seq3->flag & SELECT) == 0)) { - return false; - } - } - else { - if ((seq->seq1 && (seq->seq1->flag & SELECT)) || (seq->seq2 && (seq->seq2->flag & SELECT)) || - (seq->seq3 && (seq->seq3->flag & SELECT))) { - return false; - } - } - } - - return true; -} - -/* use to impose limits when dragging/extending - so impossible situations don't happen - * Cant use the SEQ_LEFTSEL and SEQ_LEFTSEL directly because the strip may be in a metastrip */ -void BKE_sequence_tx_handle_xlimits(Sequence *seq, int leftflag, int rightflag) -{ - if (leftflag) { - if (BKE_sequence_tx_get_final_left(seq, false) >= - BKE_sequence_tx_get_final_right(seq, false)) { - BKE_sequence_tx_set_final_left(seq, BKE_sequence_tx_get_final_right(seq, false) - 1); - } - - if (BKE_sequence_single_check(seq) == 0) { - if (BKE_sequence_tx_get_final_left(seq, false) >= seq_tx_get_end(seq)) { - BKE_sequence_tx_set_final_left(seq, seq_tx_get_end(seq) - 1); - } - - /* doesn't work now - TODO */ -#if 0 - if (seq_tx_get_start(seq) >= seq_tx_get_final_right(seq, 0)) { - int ofs; - ofs = seq_tx_get_start(seq) - seq_tx_get_final_right(seq, 0); - seq->start -= ofs; - seq_tx_set_final_left(seq, seq_tx_get_final_left(seq, 0) + ofs); - } -#endif - } - } - - if (rightflag) { - if (BKE_sequence_tx_get_final_right(seq, false) <= - BKE_sequence_tx_get_final_left(seq, false)) { - BKE_sequence_tx_set_final_right(seq, BKE_sequence_tx_get_final_left(seq, false) + 1); - } - - if (BKE_sequence_single_check(seq) == 0) { - if (BKE_sequence_tx_get_final_right(seq, false) <= seq_tx_get_start(seq)) { - BKE_sequence_tx_set_final_right(seq, seq_tx_get_start(seq) + 1); - } - } - } - - /* sounds cannot be extended past their endpoints */ - if (seq->type == SEQ_TYPE_SOUND_RAM) { - seq->startstill = 0; - seq->endstill = 0; - } -} - -void BKE_sequence_single_fix(Sequence *seq) -{ - int left, start, offset; - if (!BKE_sequence_single_check(seq)) { - return; - } - - /* make sure the image is always at the start since there is only one, - * adjusting its start should be ok */ - left = BKE_sequence_tx_get_final_left(seq, false); - start = seq->start; - if (start != left) { - offset = left - start; - BKE_sequence_tx_set_final_left(seq, BKE_sequence_tx_get_final_left(seq, false) - offset); - BKE_sequence_tx_set_final_right(seq, BKE_sequence_tx_get_final_right(seq, false) - offset); - seq->start += offset; - } -} - -bool BKE_sequence_tx_test(Sequence *seq) -{ - return !(seq->type & SEQ_TYPE_EFFECT) || (BKE_sequence_effect_get_num_inputs(seq->type) == 0); -} - -/** - * Return \a true if given \a seq needs a complete cleanup of its cache when it is transformed. - * - * Some (effect) strip types need a complete recache of themselves when they are transformed, - * because they do not 'contain' anything and do not have any explicit relations to other strips. - */ -bool BKE_sequence_tx_fullupdate_test(Sequence *seq) -{ - return BKE_sequence_tx_test(seq) && ELEM(seq->type, SEQ_TYPE_ADJUSTMENT, SEQ_TYPE_MULTICAM); -} - -static bool seq_overlap(Sequence *seq1, Sequence *seq2) -{ - return (seq1 != seq2 && seq1->machine == seq2->machine && - ((seq1->enddisp <= seq2->startdisp) || (seq1->startdisp >= seq2->enddisp)) == 0); -} - -bool BKE_sequence_test_overlap(ListBase *seqbasep, Sequence *test) -{ - Sequence *seq; - - seq = seqbasep->first; - while (seq) { - if (seq_overlap(test, seq)) { - return true; - } - - seq = seq->next; - } - return false; -} - -void BKE_sequence_translate(Scene *evil_scene, Sequence *seq, int delta) -{ - if (delta == 0) { - return; - } - - BKE_sequencer_offset_animdata(evil_scene, seq, delta); - seq->start += delta; - - if (seq->type == SEQ_TYPE_META) { - Sequence *seq_child; - for (seq_child = seq->seqbase.first; seq_child; seq_child = seq_child->next) { - BKE_sequence_translate(evil_scene, seq_child, delta); - } - } - - BKE_sequence_calc_disp(evil_scene, seq); -} - -void BKE_sequence_sound_init(Scene *scene, Sequence *seq) -{ - if (seq->type == SEQ_TYPE_META) { - Sequence *seq_child; - for (seq_child = seq->seqbase.first; seq_child; seq_child = seq_child->next) { - BKE_sequence_sound_init(scene, seq_child); - } - } - else { - if (seq->sound) { - seq->scene_sound = BKE_sound_add_scene_sound_defaults(scene, seq); - } - if (seq->scene) { - seq->scene_sound = BKE_sound_scene_add_scene_sound_defaults(scene, seq); - } - } -} - -const Sequence *BKE_sequencer_foreground_frame_get(const Scene *scene, int frame) -{ - const Editing *ed = scene->ed; - const Sequence *seq, *best_seq = NULL; - int best_machine = -1; - - if (!ed) { - return NULL; - } - - for (seq = ed->seqbasep->first; seq; seq = seq->next) { - if (seq->flag & SEQ_MUTE || seq->startdisp > frame || seq->enddisp <= frame) { - continue; - } - /* Only use strips that generate an image, not ones that combine - * other strips or apply some effect. */ - if (ELEM(seq->type, - SEQ_TYPE_IMAGE, - SEQ_TYPE_META, - SEQ_TYPE_SCENE, - SEQ_TYPE_MOVIE, - SEQ_TYPE_COLOR, - SEQ_TYPE_TEXT)) { - if (seq->machine > best_machine) { - best_seq = seq; - best_machine = seq->machine; - } - } - } - return best_seq; -} - -/* return 0 if there weren't enough space */ -bool BKE_sequence_base_shuffle_ex(ListBase *seqbasep, - Sequence *test, - Scene *evil_scene, - int channel_delta) -{ - const int orig_machine = test->machine; - BLI_assert(ELEM(channel_delta, -1, 1)); - - test->machine += channel_delta; - BKE_sequence_calc(evil_scene, test); - while (BKE_sequence_test_overlap(seqbasep, test)) { - if ((channel_delta > 0) ? (test->machine >= MAXSEQ) : (test->machine < 1)) { - break; - } - - test->machine += channel_delta; - BKE_sequence_calc( - evil_scene, - test); // XXX - I don't think this is needed since were only moving vertically, Campbell. - } - - if ((test->machine < 1) || (test->machine > MAXSEQ)) { - /* Blender 2.4x would remove the strip. - * nicer to move it to the end */ - - Sequence *seq; - int new_frame = test->enddisp; - - for (seq = seqbasep->first; seq; seq = seq->next) { - if (seq->machine == orig_machine) { - new_frame = max_ii(new_frame, seq->enddisp); - } - } - - test->machine = orig_machine; - new_frame = new_frame + (test->start - test->startdisp); /* adjust by the startdisp */ - BKE_sequence_translate(evil_scene, test, new_frame - test->start); - - BKE_sequence_calc(evil_scene, test); - return false; - } - - return true; -} - -bool BKE_sequence_base_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_scene) -{ - return BKE_sequence_base_shuffle_ex(seqbasep, test, evil_scene, 1); -} - -static int shuffle_seq_time_offset_test(ListBase *seqbasep, char dir) -{ - int offset = 0; - Sequence *seq, *seq_other; - - for (seq = seqbasep->first; seq; seq = seq->next) { - if (seq->tmp) { - for (seq_other = seqbasep->first; seq_other; seq_other = seq_other->next) { - if (!seq_other->tmp && seq_overlap(seq, seq_other)) { - if (dir == 'L') { - offset = min_ii(offset, seq_other->startdisp - seq->enddisp); - } - else { - offset = max_ii(offset, seq_other->enddisp - seq->startdisp); - } - } - } - } - } - return offset; -} - -static int shuffle_seq_time_offset(Scene *scene, ListBase *seqbasep, char dir) -{ - int ofs = 0; - int tot_ofs = 0; - Sequence *seq; - while ((ofs = shuffle_seq_time_offset_test(seqbasep, dir))) { - for (seq = seqbasep->first; seq; seq = seq->next) { - if (seq->tmp) { - /* seq_test_overlap only tests display values */ - seq->startdisp += ofs; - seq->enddisp += ofs; - } - } - - tot_ofs += ofs; - } - - for (seq = seqbasep->first; seq; seq = seq->next) { - if (seq->tmp) { - BKE_sequence_calc_disp(scene, seq); /* corrects dummy startdisp/enddisp values */ - } - } - - return tot_ofs; -} - -bool BKE_sequence_base_shuffle_time(ListBase *seqbasep, - Scene *evil_scene, - ListBase *markers, - const bool use_sync_markers) -{ - /* note: seq->tmp is used to tag strips to move */ - - Sequence *seq; - - int offset_l = shuffle_seq_time_offset(evil_scene, seqbasep, 'L'); - int offset_r = shuffle_seq_time_offset(evil_scene, seqbasep, 'R'); - int offset = (-offset_l < offset_r) ? offset_l : offset_r; - - if (offset) { - for (seq = seqbasep->first; seq; seq = seq->next) { - if (seq->tmp) { - BKE_sequence_translate(evil_scene, seq, offset); - seq->flag &= ~SEQ_OVERLAP; - } - } - - if (use_sync_markers && !(evil_scene->toolsettings->lock_markers) && (markers != NULL)) { - TimeMarker *marker; - /* affect selected markers - it's unlikely that we will want to affect all in this way? */ - for (marker = markers->first; marker; marker = marker->next) { - if (marker->flag & SELECT) { - marker->frame += offset; - } - } - } - } - - return offset ? false : true; -} - -/* Unlike _update_sound_ funcs, these ones take info from audaspace to update sequence length! */ -#ifdef WITH_AUDASPACE -static bool sequencer_refresh_sound_length_recursive(Main *bmain, Scene *scene, ListBase *seqbase) -{ - Sequence *seq; - bool changed = false; - - for (seq = seqbase->first; seq; seq = seq->next) { - if (seq->type == SEQ_TYPE_META) { - if (sequencer_refresh_sound_length_recursive(bmain, scene, &seq->seqbase)) { - BKE_sequence_calc(scene, seq); - changed = true; - } - } - else if (seq->type == SEQ_TYPE_SOUND_RAM && seq->sound) { - const float length = BKE_sound_get_length(bmain, seq->sound); - int old = seq->len; - float fac; - - seq->len = (int)ceil((double)length * FPS); - fac = (float)seq->len / (float)old; - old = seq->startofs; - seq->startofs *= fac; - seq->endofs *= fac; - seq->start += (old - seq->startofs); /* So that visual/"real" start frame does not change! */ - - BKE_sequence_calc(scene, seq); - changed = true; - } - } - return changed; -} -#endif - -void BKE_sequencer_refresh_sound_length(Main *bmain, Scene *scene) -{ -#ifdef WITH_AUDASPACE - if (scene->ed) { - sequencer_refresh_sound_length_recursive(bmain, scene, &scene->ed->seqbase); - } -#else - UNUSED_VARS(bmain, scene); -#endif -} - -void BKE_sequencer_update_sound_bounds_all(Scene *scene) -{ - Editing *ed = scene->ed; - - if (ed) { - Sequence *seq; - - for (seq = ed->seqbase.first; seq; seq = seq->next) { - if (seq->type == SEQ_TYPE_META) { - seq_update_sound_bounds_recursive(scene, seq); - } - else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) { - BKE_sequencer_update_sound_bounds(scene, seq); - } - } - } -} - -void BKE_sequencer_update_sound_bounds(Scene *scene, Sequence *seq) -{ - if (seq->type == SEQ_TYPE_SCENE) { - if (seq->scene && seq->scene_sound) { - /* 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); - } - } - else { - BKE_sound_move_scene_sound_defaults(scene, seq); - } - /* mute is set in seq_update_muting_recursive */ -} - -static void seq_update_muting_recursive(ListBase *seqbasep, Sequence *metaseq, int mute) -{ - Sequence *seq; - int seqmute; - - /* for sound we go over full meta tree to update muted state, - * since sound is played outside of evaluating the imbufs, */ - for (seq = seqbasep->first; seq; seq = seq->next) { - seqmute = (mute || (seq->flag & SEQ_MUTE)); - - if (seq->type == SEQ_TYPE_META) { - /* if this is the current meta sequence, unmute because - * all sequences above this were set to mute */ - if (seq == metaseq) { - seqmute = 0; - } - - seq_update_muting_recursive(&seq->seqbase, metaseq, seqmute); - } - else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) { - if (seq->scene_sound) { - BKE_sound_mute_scene_sound(seq->scene_sound, seqmute); - } - } - } -} - -void BKE_sequencer_update_muting(Editing *ed) -{ - if (ed) { - /* mute all sounds up to current metastack list */ - MetaStack *ms = ed->metastack.last; - - if (ms) { - seq_update_muting_recursive(&ed->seqbase, ms->parseq, 1); - } - else { - seq_update_muting_recursive(&ed->seqbase, NULL, 0); - } - } -} - -static void seq_update_sound_recursive(Scene *scene, ListBase *seqbasep, bSound *sound) -{ - Sequence *seq; - - for (seq = seqbasep->first; seq; seq = seq->next) { - if (seq->type == SEQ_TYPE_META) { - seq_update_sound_recursive(scene, &seq->seqbase, sound); - } - else if (seq->type == SEQ_TYPE_SOUND_RAM) { - if (seq->scene_sound && sound == seq->sound) { - BKE_sound_update_scene_sound(seq->scene_sound, sound); - } - } - } -} - -void BKE_sequencer_update_sound(Scene *scene, bSound *sound) -{ - if (scene->ed) { - seq_update_sound_recursive(scene, &scene->ed->seqbase, sound); - } -} - -/* in cases where we done know the sequence's listbase */ -ListBase *BKE_sequence_seqbase(ListBase *seqbase, Sequence *seq) -{ - Sequence *iseq; - ListBase *lb = NULL; - - for (iseq = seqbase->first; iseq; iseq = iseq->next) { - if (seq == iseq) { - return seqbase; - } - if (iseq->seqbase.first && (lb = BKE_sequence_seqbase(&iseq->seqbase, seq))) { - return lb; - } - } - - return NULL; -} - -Sequence *BKE_sequence_metastrip(ListBase *seqbase, Sequence *meta, Sequence *seq) -{ - Sequence *iseq; - - for (iseq = seqbase->first; iseq; iseq = iseq->next) { - Sequence *rval; - - if (seq == iseq) { - return meta; - } - if (iseq->seqbase.first && (rval = BKE_sequence_metastrip(&iseq->seqbase, iseq, seq))) { - return rval; - } - } - - return NULL; -} - -int BKE_sequence_swap(Sequence *seq_a, Sequence *seq_b, const char **error_str) -{ - char name[sizeof(seq_a->name)]; - - if (seq_a->len != seq_b->len) { - *error_str = N_("Strips must be the same length"); - return 0; - } - - /* type checking, could be more advanced but disallow sound vs non-sound copy */ - if (seq_a->type != seq_b->type) { - if (seq_a->type == SEQ_TYPE_SOUND_RAM || seq_b->type == SEQ_TYPE_SOUND_RAM) { - *error_str = N_("Strips were not compatible"); - return 0; - } - - /* disallow effects to swap with non-effects strips */ - if ((seq_a->type & SEQ_TYPE_EFFECT) != (seq_b->type & SEQ_TYPE_EFFECT)) { - *error_str = N_("Strips were not compatible"); - return 0; - } - - if ((seq_a->type & SEQ_TYPE_EFFECT) && (seq_b->type & SEQ_TYPE_EFFECT)) { - if (BKE_sequence_effect_get_num_inputs(seq_a->type) != - BKE_sequence_effect_get_num_inputs(seq_b->type)) { - *error_str = N_("Strips must have the same number of inputs"); - return 0; - } - } - } - - SWAP(Sequence, *seq_a, *seq_b); - - /* swap back names so animation fcurves don't get swapped */ - BLI_strncpy(name, seq_a->name + 2, sizeof(name)); - BLI_strncpy(seq_a->name + 2, seq_b->name + 2, sizeof(seq_b->name) - 2); - BLI_strncpy(seq_b->name + 2, name, sizeof(seq_b->name) - 2); - - /* swap back opacity, and overlay mode */ - SWAP(int, seq_a->blend_mode, seq_b->blend_mode); - SWAP(float, seq_a->blend_opacity, seq_b->blend_opacity); - - SWAP(Sequence *, seq_a->prev, seq_b->prev); - SWAP(Sequence *, seq_a->next, seq_b->next); - SWAP(int, seq_a->start, seq_b->start); - SWAP(int, seq_a->startofs, seq_b->startofs); - SWAP(int, seq_a->endofs, seq_b->endofs); - SWAP(int, seq_a->startstill, seq_b->startstill); - SWAP(int, seq_a->endstill, seq_b->endstill); - SWAP(int, seq_a->machine, seq_b->machine); - SWAP(int, seq_a->startdisp, seq_b->startdisp); - SWAP(int, seq_a->enddisp, seq_b->enddisp); - - return 1; -} - -/* r_prefix + [" + escaped_name + "] + \0 */ -#define SEQ_RNAPATH_MAXSTR ((30 + 2 + (SEQ_NAME_MAXSTR * 2) + 2) + 1) - -static size_t sequencer_rna_path_prefix(char str[SEQ_RNAPATH_MAXSTR], const char *name) -{ - char name_esc[SEQ_NAME_MAXSTR * 2]; - - BLI_strescape(name_esc, name, sizeof(name_esc)); - return BLI_snprintf_rlen( - str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc); -} - -/* XXX - hackish function needed for transforming strips! TODO - have some better solution */ -void BKE_sequencer_offset_animdata(Scene *scene, Sequence *seq, int ofs) -{ - char str[SEQ_RNAPATH_MAXSTR]; - size_t str_len; - FCurve *fcu; - - if (scene->adt == NULL || ofs == 0 || scene->adt->action == NULL) { - return; - } - - str_len = sequencer_rna_path_prefix(str, seq->name + 2); - - for (fcu = scene->adt->action->curves.first; fcu; fcu = fcu->next) { - if (STREQLEN(fcu->rna_path, str, str_len)) { - unsigned int i; - if (fcu->bezt) { - for (i = 0; i < fcu->totvert; i++) { - BezTriple *bezt = &fcu->bezt[i]; - bezt->vec[0][0] += ofs; - bezt->vec[1][0] += ofs; - bezt->vec[2][0] += ofs; - } - } - if (fcu->fpt) { - for (i = 0; i < fcu->totvert; i++) { - FPoint *fpt = &fcu->fpt[i]; - fpt->vec[0] += ofs; - } - } - } - } - - DEG_id_tag_update(&scene->adt->action->id, ID_RECALC_ANIMATION); -} - -void BKE_sequencer_dupe_animdata(Scene *scene, const char *name_src, const char *name_dst) -{ - char str_from[SEQ_RNAPATH_MAXSTR]; - size_t str_from_len; - FCurve *fcu; - FCurve *fcu_last; - FCurve *fcu_cpy; - ListBase lb = {NULL, NULL}; - - if (scene->adt == NULL || scene->adt->action == NULL) { - return; - } - - str_from_len = sequencer_rna_path_prefix(str_from, name_src); - - fcu_last = scene->adt->action->curves.last; - - for (fcu = scene->adt->action->curves.first; fcu && fcu->prev != fcu_last; fcu = fcu->next) { - if (STREQLEN(fcu->rna_path, str_from, str_from_len)) { - fcu_cpy = BKE_fcurve_copy(fcu); - BLI_addtail(&lb, fcu_cpy); - } - } - - /* notice validate is 0, keep this because the seq may not be added to the scene yet */ - BKE_animdata_fix_paths_rename( - &scene->id, scene->adt, NULL, "sequence_editor.sequences_all", name_src, name_dst, 0, 0, 0); - - /* add the original fcurves back */ - BLI_movelisttolist(&scene->adt->action->curves, &lb); -} - -/* XXX - hackish function needed to remove all fcurves belonging to a sequencer strip */ -static void seq_free_animdata(Scene *scene, Sequence *seq) -{ - char str[SEQ_RNAPATH_MAXSTR]; - size_t str_len; - FCurve *fcu; - - if (scene->adt == NULL || scene->adt->action == NULL) { - return; - } - - str_len = sequencer_rna_path_prefix(str, seq->name + 2); - - fcu = scene->adt->action->curves.first; - - while (fcu) { - if (STREQLEN(fcu->rna_path, str, str_len)) { - FCurve *next_fcu = fcu->next; - - BLI_remlink(&scene->adt->action->curves, fcu); - BKE_fcurve_free(fcu); - - fcu = next_fcu; - } - else { - fcu = fcu->next; - } - } -} - -#undef SEQ_RNAPATH_MAXSTR - -Sequence *BKE_sequence_get_by_name(ListBase *seqbase, const char *name, bool recursive) -{ - Sequence *iseq = NULL; - Sequence *rseq = NULL; - - for (iseq = seqbase->first; iseq; iseq = iseq->next) { - if (STREQ(name, iseq->name + 2)) { - return iseq; - } - if (recursive && (iseq->seqbase.first) && - (rseq = BKE_sequence_get_by_name(&iseq->seqbase, name, 1))) { - return rseq; - } - } - - return NULL; -} - -/** - * Only use as last resort when the StripElem is available but no the Sequence. - * (needed for RNA) - */ -Sequence *BKE_sequencer_from_elem(ListBase *seqbase, StripElem *se) -{ - Sequence *iseq; - - for (iseq = seqbase->first; iseq; iseq = iseq->next) { - Sequence *seq_found; - if ((iseq->strip && iseq->strip->stripdata) && - (ARRAY_HAS_ITEM(se, iseq->strip->stripdata, iseq->len))) { - break; - } - if ((seq_found = BKE_sequencer_from_elem(&iseq->seqbase, se))) { - iseq = seq_found; - break; - } - } - - return iseq; -} - -Sequence *BKE_sequencer_active_get(Scene *scene) -{ - Editing *ed = BKE_sequencer_editing_get(scene, false); - - if (ed == NULL) { - return NULL; - } - - return ed->act_seq; -} - -void BKE_sequencer_active_set(Scene *scene, Sequence *seq) -{ - Editing *ed = BKE_sequencer_editing_get(scene, false); - - if (ed == NULL) { - return; - } - - ed->act_seq = seq; -} - -int BKE_sequencer_active_get_pair(Scene *scene, Sequence **seq_act, Sequence **seq_other) -{ - Editing *ed = BKE_sequencer_editing_get(scene, false); - - *seq_act = BKE_sequencer_active_get(scene); - - if (*seq_act == NULL) { - return 0; - } - - Sequence *seq; - - *seq_other = NULL; - - for (seq = ed->seqbasep->first; seq; seq = seq->next) { - if (seq->flag & SELECT && (seq != (*seq_act))) { - if (*seq_other) { - return 0; - } - - *seq_other = seq; - } - } - - return (*seq_other != NULL); -} - -Mask *BKE_sequencer_mask_get(Scene *scene) -{ - Sequence *seq_act = BKE_sequencer_active_get(scene); - - if (seq_act && seq_act->type == SEQ_TYPE_MASK) { - return seq_act->mask; - } - - return NULL; -} - -/* api like funcs for adding */ - -static void seq_load_apply(Main *bmain, Scene *scene, Sequence *seq, SeqLoadInfo *seq_load) -{ - if (seq) { - BLI_strncpy_utf8(seq->name + 2, seq_load->name, sizeof(seq->name) - 2); - BLI_utf8_invalid_strip(seq->name + 2, strlen(seq->name + 2)); - BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); - - if (seq_load->flag & SEQ_LOAD_FRAME_ADVANCE) { - seq_load->start_frame += (seq->enddisp - seq->startdisp); - } - - if (seq_load->flag & SEQ_LOAD_REPLACE_SEL) { - seq_load->flag |= SELECT; - BKE_sequencer_active_set(scene, seq); - } - - if (seq_load->flag & SEQ_LOAD_SOUND_MONO) { - seq->sound->flags |= SOUND_FLAGS_MONO; - BKE_sound_load(bmain, seq->sound); - } - - if (seq_load->flag & SEQ_LOAD_SOUND_CACHE) { - if (seq->sound) { - seq->sound->flags |= SOUND_FLAGS_CACHING; - } + if (seq->seq1 && seq->seq1->tmp) { + seq->seq1 = seq->seq1->tmp; } - - seq_load->tot_success++; - } - else { - seq_load->tot_error++; - } -} - -static Strip *seq_strip_alloc(int type) -{ - Strip *strip = MEM_callocN(sizeof(Strip), "strip"); - - if (ELEM(type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD) == 0) { - strip->transform = MEM_callocN(sizeof(struct StripTransform), "StripTransform"); - strip->transform->scale_x = 1; - strip->transform->scale_y = 1; - strip->crop = MEM_callocN(sizeof(struct StripCrop), "StripCrop"); - } - - strip->us = 1; - return strip; -} - -Sequence *BKE_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int type) -{ - Sequence *seq; - - seq = MEM_callocN(sizeof(Sequence), "addseq"); - BLI_addtail(lb, seq); - - *((short *)seq->name) = ID_SEQ; - seq->name[2] = 0; - - seq->flag = SELECT; - seq->start = timeline_frame; - seq->machine = machine; - seq->sat = 1.0; - seq->mul = 1.0; - seq->blend_opacity = 100.0; - seq->volume = 1.0f; - seq->pitch = 1.0f; - seq->scene_sound = NULL; - seq->type = type; - - seq->strip = seq_strip_alloc(type); - seq->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Sequence Stereo Format"); - seq->cache_flag = SEQ_CACHE_STORE_RAW | SEQ_CACHE_STORE_PREPROCESSED | SEQ_CACHE_STORE_COMPOSITE; - - BKE_sequence_session_uuid_generate(seq); - - return seq; -} - -void BKE_sequence_session_uuid_generate(struct Sequence *sequence) -{ - sequence->runtime.session_uuid = BLI_session_uuid_generate(); -} - -void BKE_sequence_alpha_mode_from_extension(Sequence *seq) -{ - if (seq->strip && seq->strip->stripdata) { - const char *filename = seq->strip->stripdata->name; - seq->alpha_mode = BKE_image_alpha_mode_from_extension_ex(filename); - } -} - -float BKE_sequence_get_fps(Scene *scene, Sequence *seq) -{ - switch (seq->type) { - case SEQ_TYPE_MOVIE: { - seq_open_anim_file(scene, seq, true); - if (BLI_listbase_is_empty(&seq->anims)) { - return 0.0f; - } - StripAnim *strip_anim = seq->anims.first; - if (strip_anim->anim == NULL) { - return 0.0f; - } - short frs_sec; - float frs_sec_base; - if (IMB_anim_get_fps(strip_anim->anim, &frs_sec, &frs_sec_base, true)) { - return (float)frs_sec / frs_sec_base; - } - break; + if (seq->seq2 && seq->seq2->tmp) { + seq->seq2 = seq->seq2->tmp; } - case SEQ_TYPE_MOVIECLIP: - if (seq->clip != NULL) { - return BKE_movieclip_get_fps(seq->clip); - } - break; - case SEQ_TYPE_SCENE: - if (seq->scene != NULL) { - return (float)seq->scene->r.frs_sec / seq->scene->r.frs_sec_base; - } - break; - } - return 0.0f; -} - -/* NOTE: this function doesn't fill in image names */ -Sequence *BKE_sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) -{ - Scene *scene = CTX_data_scene(C); /* only for active seq */ - Sequence *seq; - Strip *strip; - - seq = BKE_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel, SEQ_TYPE_IMAGE); - seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */ - - /* basic defaults */ - seq->len = seq_load->len ? seq_load->len : 1; - - strip = seq->strip; - strip->stripdata = MEM_callocN(seq->len * sizeof(StripElem), "stripelem"); - BLI_strncpy(strip->dir, seq_load->path, sizeof(strip->dir)); - - if (seq_load->stereo3d_format) { - *seq->stereo3d_format = *seq_load->stereo3d_format; - } - - seq->views_format = seq_load->views_format; - seq->flag |= seq_load->flag & SEQ_USE_VIEWS; - - seq_load_apply(CTX_data_main(C), scene, seq, seq_load); - BKE_sequence_invalidate_cache_composite(scene, seq); - - return seq; -} - -#ifdef WITH_AUDASPACE -Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) -{ - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); /* only for sound */ - Editing *ed = BKE_sequencer_editing_get(scene, false); - bSound *sound; - - Sequence *seq; /* generic strip vars */ - Strip *strip; - StripElem *se; - - sound = BKE_sound_new_file(bmain, seq_load->path); /* handles relative paths */ - - SoundInfo info; - if (!BKE_sound_info_get(bmain, sound, &info)) { - BKE_id_free(bmain, sound); - return NULL; - } - - if (info.specs.channels == SOUND_CHANNELS_INVALID) { - BKE_id_free(bmain, sound); - return NULL; - } - - seq = BKE_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel, SEQ_TYPE_SOUND_RAM); - seq->sound = sound; - BLI_strncpy(seq->name + 2, "Sound", SEQ_NAME_MAXSTR - 2); - BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); - - /* basic defaults */ - /* We add a very small negative offset here, because - * ceil(132.0) == 133.0, not nice with videos, see T47135. */ - seq->len = (int)ceil((double)info.length * FPS - 1e-4); - strip = seq->strip; - - /* we only need 1 element to store the filename */ - strip->stripdata = se = MEM_callocN(sizeof(StripElem), "stripelem"); - - BLI_split_dirfile(seq_load->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name)); - - seq->scene_sound = NULL; - - BKE_sequence_calc_disp(scene, seq); - - /* last active name */ - BLI_strncpy(ed->act_sounddir, strip->dir, FILE_MAXDIR); - - seq_load_apply(bmain, scene, seq, seq_load); - - /* TODO(sergey): Shall we tag here or in the operator? */ - DEG_relations_tag_update(bmain); - - return seq; -} -#else // WITH_AUDASPACE -Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) -{ - (void)C; - (void)seqbasep; - (void)seq_load; - return NULL; -} -#endif // WITH_AUDASPACE - -static void seq_anim_add_suffix(Scene *scene, struct anim *anim, const int view_id) -{ - const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, view_id); - IMB_suffix_anim(anim, suffix); -} - -Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) -{ - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); /* only for sound */ - char path[sizeof(seq_load->path)]; - - Sequence *seq; /* generic strip vars */ - Strip *strip; - StripElem *se; - char colorspace[64] = "\0"; /* MAX_COLORSPACE_NAME */ - bool is_multiview_loaded = false; - const bool is_multiview = (seq_load->flag & SEQ_USE_VIEWS) != 0; - const int totfiles = seq_num_files(scene, seq_load->views_format, is_multiview); - struct anim **anim_arr; - int i; - - BLI_strncpy(path, seq_load->path, sizeof(path)); - BLI_path_abs(path, BKE_main_blendfile_path(bmain)); - - anim_arr = MEM_callocN(sizeof(struct anim *) * totfiles, "Video files"); - - if (is_multiview && (seq_load->views_format == R_IMF_VIEWS_INDIVIDUAL)) { - char prefix[FILE_MAX]; - const char *ext = NULL; - size_t j = 0; - - BKE_scene_multiview_view_prefix_get(scene, path, prefix, &ext); - - if (prefix[0] != '\0') { - for (i = 0; i < totfiles; i++) { - char str[FILE_MAX]; - - seq_multiview_name(scene, i, prefix, ext, str, FILE_MAX); - anim_arr[j] = openanim(str, IB_rect, 0, colorspace); - - if (anim_arr[j]) { - seq_anim_add_suffix(scene, anim_arr[j], i); - j++; - } - } - - if (j == 0) { - MEM_freeN(anim_arr); - return NULL; - } - is_multiview_loaded = true; + if (seq->seq3 && seq->seq3->tmp) { + seq->seq3 = seq->seq3->tmp; } } - - if (is_multiview_loaded == false) { - anim_arr[0] = openanim(path, IB_rect, 0, colorspace); - - if (anim_arr[0] == NULL) { - MEM_freeN(anim_arr); - return NULL; + else if (seq->type == SEQ_TYPE_META) { + Sequence *seqn; + for (seqn = seq->seqbase.first; seqn; seqn = seqn->next) { + seq_new_fix_links_recursive(seqn); } } - if (seq_load->flag & SEQ_LOAD_MOVIE_SOUND) { - seq_load->channel++; - } - seq = BKE_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel, SEQ_TYPE_MOVIE); - - /* multiview settings */ - if (seq_load->stereo3d_format) { - *seq->stereo3d_format = *seq_load->stereo3d_format; - seq->views_format = seq_load->views_format; - } - seq->flag |= seq_load->flag & SEQ_USE_VIEWS; - - seq->type = SEQ_TYPE_MOVIE; - seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */ - - for (i = 0; i < totfiles; i++) { - if (anim_arr[i]) { - StripAnim *sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim"); - BLI_addtail(&seq->anims, sanim); - sanim->anim = anim_arr[i]; - } - else { - break; + for (smd = seq->modifiers.first; smd; smd = smd->next) { + if (smd->mask_sequence && smd->mask_sequence->tmp) { + smd->mask_sequence = smd->mask_sequence->tmp; } } - - IMB_anim_load_metadata(anim_arr[0]); - - seq->anim_preseek = IMB_anim_get_preseek(anim_arr[0]); - BLI_strncpy(seq->name + 2, "Movie", SEQ_NAME_MAXSTR - 2); - BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); - - /* adjust scene's frame rate settings to match */ - if (seq_load->flag & SEQ_LOAD_SYNC_FPS) { - IMB_anim_get_fps(anim_arr[0], &scene->r.frs_sec, &scene->r.frs_sec_base, true); - } - - /* basic defaults */ - seq->len = IMB_anim_get_duration(anim_arr[0], IMB_TC_RECORD_RUN); - strip = seq->strip; - - BLI_strncpy(seq->strip->colorspace_settings.name, - colorspace, - sizeof(seq->strip->colorspace_settings.name)); - - /* we only need 1 element for MOVIE strips */ - strip->stripdata = se = MEM_callocN(sizeof(StripElem), "stripelem"); - - BLI_split_dirfile(seq_load->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name)); - - BKE_sequence_calc_disp(scene, seq); - - if (seq_load->name[0] == '\0') { - BLI_strncpy(seq_load->name, se->name, sizeof(seq_load->name)); - } - - if (seq_load->flag & SEQ_LOAD_MOVIE_SOUND) { - int start_frame_back = seq_load->start_frame; - seq_load->channel--; - seq_load->seq_sound = BKE_sequencer_add_sound_strip(C, seqbasep, seq_load); - seq_load->start_frame = start_frame_back; - } - - /* can be NULL */ - seq_load_apply(CTX_data_main(C), scene, seq, seq_load); - BKE_sequence_invalidate_cache_composite(scene, seq); - - MEM_freeN(anim_arr); - return seq; } +/** \} */ +/* -------------------------------------------------------------------- */ +/** \name Duplicate functions + * \{ */ static Sequence *seq_dupli(const Scene *scene_src, Scene *scene_dst, ListBase *new_seq_list, @@ -2936,35 +419,6 @@ static Sequence *seq_dupli(const Scene *scene_src, return seqn; } -static void seq_new_fix_links_recursive(Sequence *seq) -{ - SequenceModifierData *smd; - - if (seq->type & SEQ_TYPE_EFFECT) { - if (seq->seq1 && seq->seq1->tmp) { - seq->seq1 = seq->seq1->tmp; - } - if (seq->seq2 && seq->seq2->tmp) { - seq->seq2 = seq->seq2->tmp; - } - if (seq->seq3 && seq->seq3->tmp) { - seq->seq3 = seq->seq3->tmp; - } - } - else if (seq->type == SEQ_TYPE_META) { - Sequence *seqn; - for (seqn = seq->seqbase.first; seqn; seqn = seqn->next) { - seq_new_fix_links_recursive(seqn); - } - } - - for (smd = seq->modifiers.first; smd; smd = smd->next) { - if (smd->mask_sequence && smd->mask_sequence->tmp) { - smd->mask_sequence = smd->mask_sequence->tmp; - } - } -} - static Sequence *sequence_dupli_recursive_do(const Scene *scene_src, Scene *scene_dst, ListBase *new_seq_list, @@ -3044,297 +498,115 @@ void BKE_sequence_base_dupli_recursive(const Scene *scene_src, seq_new_fix_links_recursive(seq); } } +/* r_prefix + [" + escaped_name + "] + \0 */ +#define SEQ_RNAPATH_MAXSTR ((30 + 2 + (SEQ_NAME_MAXSTR * 2) + 2) + 1) -/* called on draw, needs to be fast, - * we could cache and use a flag if we want to make checks for file paths resolving for eg. */ -bool BKE_sequence_is_valid_check(Sequence *seq) +static size_t sequencer_rna_path_prefix(char str[SEQ_RNAPATH_MAXSTR], const char *name) { - switch (seq->type) { - case SEQ_TYPE_MASK: - return (seq->mask != NULL); - case SEQ_TYPE_MOVIECLIP: - return (seq->clip != NULL); - case SEQ_TYPE_SCENE: - return (seq->scene != NULL); - case SEQ_TYPE_SOUND_RAM: - return (seq->sound != NULL); - } + char name_esc[SEQ_NAME_MAXSTR * 2]; - return true; + BLI_strescape(name_esc, name, sizeof(name_esc)); + return BLI_snprintf_rlen( + str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc); } -int BKE_sequencer_find_next_prev_edit(Scene *scene, - int timeline_frame, - const short side, - const bool do_skip_mute, - const bool do_center, - const bool do_unselected) +/* XXX - hackish function needed for transforming strips! TODO - have some better solution */ +void BKE_sequencer_offset_animdata(Scene *scene, Sequence *seq, int ofs) { - Editing *ed = BKE_sequencer_editing_get(scene, false); - Sequence *seq; - - int dist, best_dist, best_frame = timeline_frame; - int seq_frames[2], seq_frames_tot; - - /* In case where both is passed, - * frame just finds the nearest end while frame_left the nearest start. */ - - best_dist = MAXFRAME * 2; + char str[SEQ_RNAPATH_MAXSTR]; + size_t str_len; + FCurve *fcu; - if (ed == NULL) { - return timeline_frame; + if (scene->adt == NULL || ofs == 0 || scene->adt->action == NULL) { + return; } - for (seq = ed->seqbasep->first; seq; seq = seq->next) { - int i; - - if (do_skip_mute && (seq->flag & SEQ_MUTE)) { - continue; - } - - if (do_unselected && (seq->flag & SELECT)) { - continue; - } - - if (do_center) { - seq_frames[0] = (seq->startdisp + seq->enddisp) / 2; - seq_frames_tot = 1; - } - else { - seq_frames[0] = seq->startdisp; - seq_frames[1] = seq->enddisp; - - seq_frames_tot = 2; - } - - for (i = 0; i < seq_frames_tot; i++) { - const int seq_frame = seq_frames[i]; - - dist = MAXFRAME * 2; + str_len = sequencer_rna_path_prefix(str, seq->name + 2); - switch (side) { - case SEQ_SIDE_LEFT: - if (seq_frame < timeline_frame) { - dist = timeline_frame - seq_frame; - } - break; - case SEQ_SIDE_RIGHT: - if (seq_frame > timeline_frame) { - dist = seq_frame - timeline_frame; - } - break; - case SEQ_SIDE_BOTH: - dist = abs(seq_frame - timeline_frame); - break; + for (fcu = scene->adt->action->curves.first; fcu; fcu = fcu->next) { + if (STREQLEN(fcu->rna_path, str, str_len)) { + unsigned int i; + if (fcu->bezt) { + for (i = 0; i < fcu->totvert; i++) { + BezTriple *bezt = &fcu->bezt[i]; + bezt->vec[0][0] += ofs; + bezt->vec[1][0] += ofs; + bezt->vec[2][0] += ofs; + } } - - if (dist < best_dist) { - best_frame = seq_frame; - best_dist = dist; + if (fcu->fpt) { + for (i = 0; i < fcu->totvert; i++) { + FPoint *fpt = &fcu->fpt[i]; + fpt->vec[0] += ofs; + } } } } - return best_frame; + DEG_id_tag_update(&scene->adt->action->id, ID_RECALC_ANIMATION); } -static void sequencer_all_free_anim_ibufs(ListBase *seqbase, int timeline_frame) +void BKE_sequencer_dupe_animdata(Scene *scene, const char *name_src, const char *name_dst) { - for (Sequence *seq = seqbase->first; seq != NULL; seq = seq->next) { - if (seq->enddisp < timeline_frame || seq->startdisp > timeline_frame) { - BKE_sequence_free_anim(seq); - } - if (seq->type == SEQ_TYPE_META) { - sequencer_all_free_anim_ibufs(&seq->seqbase, timeline_frame); - } - } -} + char str_from[SEQ_RNAPATH_MAXSTR]; + size_t str_from_len; + FCurve *fcu; + FCurve *fcu_last; + FCurve *fcu_cpy; + ListBase lb = {NULL, NULL}; -void BKE_sequencer_all_free_anim_ibufs(Scene *scene, int timeline_frame) -{ - Editing *ed = BKE_sequencer_editing_get(scene, false); - if (ed == NULL) { + if (scene->adt == NULL || scene->adt->action == NULL) { return; } - sequencer_all_free_anim_ibufs(&ed->seqbase, timeline_frame); - BKE_sequencer_cache_cleanup(scene); -} - -static bool sequencer_seq_generates_image(Sequence *seq) -{ - switch (seq->type) { - case SEQ_TYPE_IMAGE: - case SEQ_TYPE_SCENE: - case SEQ_TYPE_MOVIE: - case SEQ_TYPE_MOVIECLIP: - case SEQ_TYPE_MASK: - case SEQ_TYPE_COLOR: - case SEQ_TYPE_TEXT: - return true; - } - return false; -} -static Sequence *sequencer_check_scene_recursion(Scene *scene, ListBase *seqbase) -{ - LISTBASE_FOREACH (Sequence *, seq, seqbase) { - if (seq->type == SEQ_TYPE_SCENE && seq->scene == scene) { - return seq; - } - - if (seq->type == SEQ_TYPE_SCENE && (seq->flag & SEQ_SCENE_STRIPS)) { - if (sequencer_check_scene_recursion(scene, &seq->scene->ed->seqbase)) { - return seq; - } - } - - if (seq->type == SEQ_TYPE_META && sequencer_check_scene_recursion(scene, &seq->seqbase)) { - return seq; - } - } - - return NULL; -} - -bool BKE_sequencer_check_scene_recursion(Scene *scene, ReportList *reports) -{ - Editing *ed = BKE_sequencer_editing_get(scene, false); - if (ed == NULL) { - return false; - } - - Sequence *recursive_seq = sequencer_check_scene_recursion(scene, &ed->seqbase); + str_from_len = sequencer_rna_path_prefix(str_from, name_src); - if (recursive_seq != NULL) { - BKE_reportf(reports, - RPT_WARNING, - "Recursion detected in video sequencer. Strip %s at frame %d will not be rendered", - recursive_seq->name + 2, - recursive_seq->startdisp); + fcu_last = scene->adt->action->curves.last; - LISTBASE_FOREACH (Sequence *, seq, &ed->seqbase) { - if (seq->type != SEQ_TYPE_SCENE && sequencer_seq_generates_image(seq)) { - /* There are other strips to render, so render them. */ - return false; - } + for (fcu = scene->adt->action->curves.first; fcu && fcu->prev != fcu_last; fcu = fcu->next) { + if (STREQLEN(fcu->rna_path, str_from, str_from_len)) { + fcu_cpy = BKE_fcurve_copy(fcu); + BLI_addtail(&lb, fcu_cpy); } - /* No other strips to render - cancel operator. */ - return true; } - return false; -} - -/* Check if "seq_main" (indirectly) uses strip "seq". */ -bool BKE_sequencer_render_loop_check(Sequence *seq_main, Sequence *seq) -{ - if (seq_main == NULL || seq == NULL) { - return false; - } - - if (seq_main == seq) { - return true; - } - - if ((seq_main->seq1 && BKE_sequencer_render_loop_check(seq_main->seq1, seq)) || - (seq_main->seq2 && BKE_sequencer_render_loop_check(seq_main->seq2, seq)) || - (seq_main->seq3 && BKE_sequencer_render_loop_check(seq_main->seq3, seq))) { - return true; - } - - SequenceModifierData *smd; - for (smd = seq_main->modifiers.first; smd; smd = smd->next) { - if (smd->mask_sequence && BKE_sequencer_render_loop_check(smd->mask_sequence, seq)) { - return true; - } - } + /* notice validate is 0, keep this because the seq may not be added to the scene yet */ + BKE_animdata_fix_paths_rename( + &scene->id, scene->adt, NULL, "sequence_editor.sequences_all", name_src, name_dst, 0, 0, 0); - return false; + /* add the original fcurves back */ + BLI_movelisttolist(&scene->adt->action->curves, &lb); } -static void sequencer_flag_users_for_removal(Scene *scene, ListBase *seqbase, Sequence *seq) +/* XXX - hackish function needed to remove all fcurves belonging to a sequencer strip */ +static void seq_free_animdata(Scene *scene, Sequence *seq) { - LISTBASE_FOREACH (Sequence *, user_seq, seqbase) { - /* Look in metas for usage of seq. */ - if (user_seq->type == SEQ_TYPE_META) { - sequencer_flag_users_for_removal(scene, &user_seq->seqbase, seq); - } - - /* Clear seq from modifiers. */ - SequenceModifierData *smd; - for (smd = user_seq->modifiers.first; smd; smd = smd->next) { - if (smd->mask_sequence == seq) { - smd->mask_sequence = NULL; - } - } - - /* Remove effects, that use seq. */ - if ((user_seq->seq1 && user_seq->seq1 == seq) || (user_seq->seq2 && user_seq->seq2 == seq) || - (user_seq->seq3 && user_seq->seq3 == seq)) { - user_seq->flag |= SEQ_FLAG_DELETE; - /* Strips can be used as mask even if not in same seqbase. */ - sequencer_flag_users_for_removal(scene, &scene->ed->seqbase, user_seq); - } - } -} + char str[SEQ_RNAPATH_MAXSTR]; + size_t str_len; + FCurve *fcu; -/* Flag seq and its users (effects) for removal. */ -void BKE_sequencer_flag_for_removal(Scene *scene, ListBase *seqbase, Sequence *seq) -{ - if (seq == NULL || (seq->flag & SEQ_FLAG_DELETE) != 0) { + if (scene->adt == NULL || scene->adt->action == NULL) { return; } - /* Flag and remove meta children. */ - if (seq->type == SEQ_TYPE_META) { - LISTBASE_FOREACH (Sequence *, meta_child, &seq->seqbase) { - BKE_sequencer_flag_for_removal(scene, &seq->seqbase, meta_child); - } - } - - seq->flag |= SEQ_FLAG_DELETE; - sequencer_flag_users_for_removal(scene, seqbase, seq); -} + str_len = sequencer_rna_path_prefix(str, seq->name + 2); -/* Remove all flagged sequences, return true if sequence is removed. */ -void BKE_sequencer_remove_flagged_sequences(Scene *scene, ListBase *seqbase) -{ - LISTBASE_FOREACH_MUTABLE (Sequence *, seq, seqbase) { - if (seq->flag & SEQ_FLAG_DELETE) { - if (seq->type == SEQ_TYPE_META) { - BKE_sequencer_remove_flagged_sequences(scene, &seq->seqbase); - } - BLI_remlink(seqbase, seq); - BKE_sequence_free(scene, seq, true); - } - } -} + fcu = scene->adt->action->curves.first; -void BKE_sequencer_check_uuids_unique_and_report(const Scene *scene) -{ - if (scene->ed == NULL) { - return; - } + while (fcu) { + if (STREQLEN(fcu->rna_path, str, str_len)) { + FCurve *next_fcu = fcu->next; - struct GSet *used_uuids = BLI_gset_new( - BLI_session_uuid_ghash_hash, BLI_session_uuid_ghash_compare, "sequencer used uuids"); + BLI_remlink(&scene->adt->action->curves, fcu); + BKE_fcurve_free(fcu); - const Sequence *sequence; - SEQ_ALL_BEGIN (scene->ed, sequence) { - const SessionUUID *session_uuid = &sequence->runtime.session_uuid; - if (!BLI_session_uuid_is_generated(session_uuid)) { - printf("Sequence %s does not have UUID generated.\n", sequence->name); - continue; + fcu = next_fcu; } - - if (BLI_gset_lookup(used_uuids, session_uuid) != NULL) { - printf("Sequence %s has duplicate UUID generated.\n", sequence->name); - continue; + else { + fcu = fcu->next; } - - BLI_gset_insert(used_uuids, (void *)session_uuid); } - SEQ_ALL_END; - - BLI_gset_free(used_uuids, NULL); } + +#undef SEQ_RNAPATH_MAXSTR +/** \} */ |