diff options
Diffstat (limited to 'source/blender/sequencer/intern/sequencer.c')
-rw-r--r-- | source/blender/sequencer/intern/sequencer.c | 337 |
1 files changed, 329 insertions, 8 deletions
diff --git a/source/blender/sequencer/intern/sequencer.c b/source/blender/sequencer/intern/sequencer.c index 7dc19cf39a6..49d08d0e022 100644 --- a/source/blender/sequencer/intern/sequencer.c +++ b/source/blender/sequencer/intern/sequencer.c @@ -24,11 +24,14 @@ * \ingroup bke */ +#define DNA_DEPRECATED_ALLOW + #include "MEM_guardedalloc.h" #include "DNA_anim_types.h" #include "DNA_scene_types.h" #include "DNA_sequence_types.h" +#include "DNA_sound_types.h" #include "BLI_listbase.h" #include "BLI_string.h" @@ -44,14 +47,19 @@ #include "IMB_colormanagement.h" #include "IMB_imbuf.h" +#include "SEQ_edit.h" #include "SEQ_effects.h" #include "SEQ_iterator.h" #include "SEQ_modifier.h" +#include "SEQ_proxy.h" #include "SEQ_relations.h" #include "SEQ_select.h" #include "SEQ_sequencer.h" +#include "SEQ_sound.h" #include "SEQ_utils.h" +#include "BLO_read_write.h" + #include "image_cache.h" #include "prefetch.h" #include "sequencer.h" @@ -217,16 +225,19 @@ void SEQ_sequence_free(Scene *scene, Sequence *seq, const bool do_clean_animdata /* 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) +void seq_free_sequence_recurse(Scene *scene, + Sequence *seq, + const bool do_id_user, + const bool do_clean_animdata) { Sequence *iseq, *iseq_next; for (iseq = seq->seqbase.first; iseq; iseq = iseq_next) { iseq_next = iseq->next; - seq_free_sequence_recurse(scene, iseq, do_id_user); + seq_free_sequence_recurse(scene, iseq, do_id_user, do_clean_animdata); } - seq_sequence_free_ex(scene, seq, false, do_id_user, true); + seq_sequence_free_ex(scene, seq, false, do_id_user, do_clean_animdata); } Editing *SEQ_editing_get(Scene *scene, bool alloc) @@ -255,7 +266,6 @@ Editing *SEQ_editing_ensure(Scene *scene) void SEQ_editing_free(Scene *scene, const bool do_id_user) { Editing *ed = scene->ed; - Sequence *seq; if (ed == NULL) { return; @@ -264,11 +274,10 @@ void SEQ_editing_free(Scene *scene, const bool do_id_user) seq_prefetch_free(scene); seq_cache_destruct(scene); - SEQ_ALL_BEGIN (ed, seq) { - /* handle cache freeing above */ - seq_sequence_free_ex(scene, seq, false, do_id_user, false); + /* handle cache freeing above */ + LISTBASE_FOREACH_MUTABLE (Sequence *, seq, &ed->seqbase) { + seq_free_sequence_recurse(scene, seq, do_id_user, false); } - SEQ_ALL_END; BLI_freelistN(&ed->metastack); SEQ_sequence_lookup_free(scene); @@ -732,3 +741,315 @@ SequencerToolSettings *SEQ_tool_settings_copy(SequencerToolSettings *tool_settin } /** \} */ + +static bool seq_set_strip_done_cb(Sequence *seq, void *UNUSED(userdata)) +{ + if (seq->strip) { + seq->strip->done = false; + } + return true; +} + +static bool seq_write_data_cb(Sequence *seq, void *userdata) +{ + BlendWriter *writer = (BlendWriter *)userdata; + BLO_write_struct(writer, Sequence, seq); + if (seq->strip && seq->strip->done == 0) { + /* write strip with 'done' at 0 because readfile */ + + // TODO this doesn't depend on the `Strip` data to be present? + if (seq->effectdata) { + switch (seq->type) { + case SEQ_TYPE_COLOR: + BLO_write_struct(writer, SolidColorVars, seq->effectdata); + break; + case SEQ_TYPE_SPEED: + BLO_write_struct(writer, SpeedControlVars, seq->effectdata); + break; + case SEQ_TYPE_WIPE: + BLO_write_struct(writer, WipeVars, seq->effectdata); + break; + case SEQ_TYPE_GLOW: + BLO_write_struct(writer, GlowVars, seq->effectdata); + break; + case SEQ_TYPE_TRANSFORM: + BLO_write_struct(writer, TransformVars, seq->effectdata); + break; + case SEQ_TYPE_GAUSSIAN_BLUR: + BLO_write_struct(writer, GaussianBlurVars, seq->effectdata); + break; + case SEQ_TYPE_TEXT: + BLO_write_struct(writer, TextVars, seq->effectdata); + break; + case SEQ_TYPE_COLORMIX: + BLO_write_struct(writer, ColorMixVars, seq->effectdata); + break; + } + } + + BLO_write_struct(writer, Stereo3dFormat, seq->stereo3d_format); + + Strip *strip = seq->strip; + BLO_write_struct(writer, Strip, strip); + if (strip->crop) { + BLO_write_struct(writer, StripCrop, strip->crop); + } + if (strip->transform) { + BLO_write_struct(writer, StripTransform, strip->transform); + } + if (strip->proxy) { + BLO_write_struct(writer, StripProxy, strip->proxy); + } + if (seq->type == SEQ_TYPE_IMAGE) { + BLO_write_struct_array(writer, + StripElem, + MEM_allocN_len(strip->stripdata) / sizeof(struct StripElem), + strip->stripdata); + } + else if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) { + BLO_write_struct(writer, StripElem, strip->stripdata); + } + + strip->done = true; + } + + if (seq->prop) { + IDP_BlendWrite(writer, seq->prop); + } + + SEQ_modifier_blend_write(writer, &seq->modifiers); + return true; +} + +void SEQ_blend_write(BlendWriter *writer, ListBase *seqbase) +{ + /* reset write flags */ + SEQ_for_each_callback(seqbase, seq_set_strip_done_cb, NULL); + + SEQ_for_each_callback(seqbase, seq_write_data_cb, writer); +} + +static bool seq_read_data_cb(Sequence *seq, void *user_data) +{ + BlendDataReader *reader = (BlendDataReader *)user_data; + + /* Do as early as possible, so that other parts of reading can rely on valid session UUID. */ + SEQ_relations_session_uuid_generate(seq); + + BLO_read_data_address(reader, &seq->seq1); + BLO_read_data_address(reader, &seq->seq2); + BLO_read_data_address(reader, &seq->seq3); + + /* a patch: after introduction of effects with 3 input strips */ + if (seq->seq3 == NULL) { + seq->seq3 = seq->seq2; + } + + BLO_read_data_address(reader, &seq->effectdata); + BLO_read_data_address(reader, &seq->stereo3d_format); + + if (seq->type & SEQ_TYPE_EFFECT) { + seq->flag |= SEQ_EFFECT_NOT_LOADED; + } + + if (seq->type == SEQ_TYPE_TEXT) { + TextVars *t = seq->effectdata; + t->text_blf_id = SEQ_FONT_NOT_LOADED; + } + + BLO_read_data_address(reader, &seq->prop); + IDP_BlendDataRead(reader, &seq->prop); + + BLO_read_data_address(reader, &seq->strip); + if (seq->strip && seq->strip->done == 0) { + seq->strip->done = true; + + if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) { + BLO_read_data_address(reader, &seq->strip->stripdata); + } + else { + seq->strip->stripdata = NULL; + } + BLO_read_data_address(reader, &seq->strip->crop); + BLO_read_data_address(reader, &seq->strip->transform); + BLO_read_data_address(reader, &seq->strip->proxy); + if (seq->strip->proxy) { + seq->strip->proxy->anim = NULL; + } + else if (seq->flag & SEQ_USE_PROXY) { + SEQ_proxy_set(seq, true); + } + + /* need to load color balance to it could be converted to modifier */ + BLO_read_data_address(reader, &seq->strip->color_balance); + } + + SEQ_modifier_blend_read_data(reader, &seq->modifiers); + return true; +} +void SEQ_blend_read(BlendDataReader *reader, ListBase *seqbase) +{ + SEQ_for_each_callback(seqbase, seq_read_data_cb, reader); +} + +typedef struct Read_lib_data { + BlendLibReader *reader; + Scene *scene; +} Read_lib_data; + +static bool seq_read_lib_cb(Sequence *seq, void *user_data) +{ + Read_lib_data *data = (Read_lib_data *)user_data; + BlendLibReader *reader = data->reader; + Scene *sce = data->scene; + + IDP_BlendReadLib(reader, seq->prop); + + if (seq->ipo) { + /* XXX: deprecated - old animation system. */ + BLO_read_id_address(reader, sce->id.lib, &seq->ipo); + } + seq->scene_sound = NULL; + if (seq->scene) { + BLO_read_id_address(reader, sce->id.lib, &seq->scene); + seq->scene_sound = NULL; + } + if (seq->clip) { + BLO_read_id_address(reader, sce->id.lib, &seq->clip); + } + if (seq->mask) { + BLO_read_id_address(reader, sce->id.lib, &seq->mask); + } + if (seq->scene_camera) { + BLO_read_id_address(reader, sce->id.lib, &seq->scene_camera); + } + if (seq->sound) { + seq->scene_sound = NULL; + if (seq->type == SEQ_TYPE_SOUND_HD) { + seq->type = SEQ_TYPE_SOUND_RAM; + } + else { + BLO_read_id_address(reader, sce->id.lib, &seq->sound); + } + if (seq->sound) { + id_us_plus_no_lib((ID *)seq->sound); + seq->scene_sound = NULL; + } + } + if (seq->type == SEQ_TYPE_TEXT) { + TextVars *t = seq->effectdata; + BLO_read_id_address(reader, sce->id.lib, &t->text_font); + } + BLI_listbase_clear(&seq->anims); + + SEQ_modifier_blend_read_lib(reader, sce, &seq->modifiers); + return true; +} + +void SEQ_blend_read_lib(BlendLibReader *reader, Scene *scene, ListBase *seqbase) +{ + Read_lib_data data = {reader, scene}; + SEQ_for_each_callback(seqbase, seq_read_lib_cb, &data); +} + +static bool seq_blend_read_expand(Sequence *seq, void *user_data) +{ + BlendExpander *expander = (BlendExpander *)user_data; + + IDP_BlendReadExpand(expander, seq->prop); + + if (seq->scene) { + BLO_expand(expander, seq->scene); + } + if (seq->scene_camera) { + BLO_expand(expander, seq->scene_camera); + } + if (seq->clip) { + BLO_expand(expander, seq->clip); + } + if (seq->mask) { + BLO_expand(expander, seq->mask); + } + if (seq->sound) { + BLO_expand(expander, seq->sound); + } + + if (seq->type == SEQ_TYPE_TEXT && seq->effectdata) { + TextVars *data = seq->effectdata; + BLO_expand(expander, data->text_font); + } + return true; +} + +void SEQ_blend_read_expand(BlendExpander *expander, ListBase *seqbase) +{ + SEQ_for_each_callback(seqbase, seq_blend_read_expand, expander); +} + +/* Depsgraph update functions. */ + +static bool seq_disable_sound_strips_cb(Sequence *seq, void *user_data) +{ + Scene *scene = (Scene *)user_data; + if (seq->scene_sound != NULL) { + BKE_sound_remove_scene_sound(scene, seq->scene_sound); + seq->scene_sound = NULL; + } + return true; +} + +static bool seq_update_seq_cb(Sequence *seq, void *user_data) +{ + Scene *scene = (Scene *)user_data; + if (seq->scene_sound == NULL) { + if (seq->sound != NULL) { + seq->scene_sound = BKE_sound_add_scene_sound_defaults(scene, seq); + } + else if (seq->type == SEQ_TYPE_SCENE) { + if (seq->scene != NULL) { + BKE_sound_ensure_scene(seq->scene); + seq->scene_sound = BKE_sound_scene_add_scene_sound_defaults(scene, seq); + } + } + } + if (seq->scene_sound != NULL) { + /* Make sure changing volume via sequence's properties panel works correct. + * + * Ideally, the entire BKE_scene_update_sound() will happen from a dependency graph, so + * then it is no longer needed to do such manual forced updates. */ + if (seq->type == SEQ_TYPE_SCENE && seq->scene != NULL) { + BKE_sound_set_scene_volume(seq->scene, seq->scene->audio.volume); + if ((seq->flag & SEQ_SCENE_STRIPS) == 0 && seq->scene->sound_scene != NULL && + seq->scene->ed != NULL) { + SEQ_for_each_callback(&seq->scene->ed->seqbase, seq_disable_sound_strips_cb, seq->scene); + } + } + if (seq->sound != NULL) { + if (scene->id.recalc & ID_RECALC_AUDIO || seq->sound->id.recalc & ID_RECALC_AUDIO) { + BKE_sound_update_scene_sound(seq->scene_sound, seq->sound); + } + } + BKE_sound_set_scene_sound_volume( + seq->scene_sound, seq->volume, (seq->flag & SEQ_AUDIO_VOLUME_ANIMATED) != 0); + BKE_sound_set_scene_sound_pitch( + seq->scene_sound, seq->pitch, (seq->flag & SEQ_AUDIO_PITCH_ANIMATED) != 0); + BKE_sound_set_scene_sound_pan( + seq->scene_sound, seq->pan, (seq->flag & SEQ_AUDIO_PAN_ANIMATED) != 0); + } + return true; +} + +/* Evaluate parts of sequences which needs to be done as a part of a dependency graph evaluation. + * This does NOT include actual rendering of the strips, but rather makes them up-to-date for + * animation playback and makes them ready for the sequencer's rendering pipeline to render them. + */ +void SEQ_eval_sequences(Depsgraph *depsgraph, Scene *scene, ListBase *seqbase) +{ + DEG_debug_print_eval(depsgraph, __func__, scene->id.name, scene); + BKE_sound_ensure_scene(scene); + + SEQ_for_each_callback(seqbase, seq_update_seq_cb, scene); + + SEQ_edit_update_muting(scene->ed); + SEQ_sound_update_bounds_all(scene); +} |