Changeset View
Changeset View
Standalone View
Standalone View
source/blender/sequencer/intern/strip_edit.c
| Show All 37 Lines | |||||
| #include "BKE_scene.h" | #include "BKE_scene.h" | ||||
| #include "BKE_sound.h" | #include "BKE_sound.h" | ||||
| #include "strip_time.h" | #include "strip_time.h" | ||||
| #include "SEQ_add.h" | #include "SEQ_add.h" | ||||
| #include "SEQ_edit.h" | #include "SEQ_edit.h" | ||||
| #include "SEQ_effects.h" | #include "SEQ_effects.h" | ||||
| #include "SEQ_iterator.h" | |||||
| #include "SEQ_sequencer.h" | #include "SEQ_sequencer.h" | ||||
| #include "SEQ_time.h" | #include "SEQ_time.h" | ||||
| #include "SEQ_transform.h" | #include "SEQ_transform.h" | ||||
| #include "SEQ_utils.h" | |||||
| int SEQ_edit_sequence_swap(Sequence *seq_a, Sequence *seq_b, const char **error_str) | int SEQ_edit_sequence_swap(Sequence *seq_a, Sequence *seq_b, const char **error_str) | ||||
| { | { | ||||
| char name[sizeof(seq_a->name)]; | char name[sizeof(seq_a->name)]; | ||||
| if (seq_a->len != seq_b->len) { | if (seq_a->len != seq_b->len) { | ||||
| *error_str = N_("Strips must be the same length"); | *error_str = N_("Strips must be the same length"); | ||||
| return 0; | return 0; | ||||
| ▲ Show 20 Lines • Show All 140 Lines • ▼ Show 20 Lines | if (seq->flag & SEQ_FLAG_DELETE) { | ||||
| SEQ_edit_remove_flagged_sequences(scene, &seq->seqbase); | SEQ_edit_remove_flagged_sequences(scene, &seq->seqbase); | ||||
| } | } | ||||
| BLI_remlink(seqbase, seq); | BLI_remlink(seqbase, seq); | ||||
| SEQ_sequence_free(scene, seq, true); | SEQ_sequence_free(scene, seq, true); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void seq_edit_clear_chain_tag(ListBase *seqbase) | |||||
| { | |||||
| LISTBASE_FOREACH (Sequence *, seq, seqbase) { | |||||
| seq->flag &= ~SEQ_FLAG_CHAIN_TAG; | |||||
| } | |||||
| } | |||||
| static int seq_edit_tag_chain(Sequence *seq, ListBase *seqbase) | |||||
| { | |||||
| seq->flag |= SEQ_FLAG_CHAIN_TAG; | |||||
| int tagged_strips_count = 1; | |||||
| /* Tag used strips. */ | |||||
| if (seq->type & SEQ_TYPE_EFFECT) { | |||||
| if (seq->seq1 && (seq->seq1->flag & SEQ_FLAG_CHAIN_TAG) == 0) { | |||||
| tagged_strips_count += seq_edit_tag_chain(seq->seq1, seqbase); | |||||
| } | |||||
| if (seq->seq2 && (seq->seq2->flag & SEQ_FLAG_CHAIN_TAG) == 0) { | |||||
| tagged_strips_count += seq_edit_tag_chain(seq->seq2, seqbase); | |||||
| } | |||||
| if (seq->seq3 && (seq->seq3->flag & SEQ_FLAG_CHAIN_TAG) == 0) { | |||||
| tagged_strips_count += seq_edit_tag_chain(seq->seq3, seqbase); | |||||
| } | |||||
| } | |||||
| /* Tag strips that use seq. */ | |||||
| LISTBASE_FOREACH (Sequence *, seq_test, seqbase) { | |||||
| if (seq_test->seq1 == seq || seq_test->seq2 == seq || seq_test->seq3 == seq) { | |||||
| if ((seq_test->flag & SEQ_FLAG_CHAIN_TAG) == 0) { | |||||
| tagged_strips_count += seq_edit_tag_chain(seq_test, seqbase); | |||||
| } | |||||
| } | |||||
| } | |||||
| return tagged_strips_count; | |||||
| } | |||||
| static void seq_edit_move_chain_to_list_base(ListBase *seqbase_dst, ListBase *seqbase_src) | |||||
| { | |||||
| LISTBASE_FOREACH_MUTABLE (Sequence *, seq, seqbase_src) { | |||||
| if ((seq->flag & SEQ_FLAG_CHAIN_TAG) != 0) { | |||||
| BLI_remlink(seqbase_src, seq); | |||||
| BLI_addtail(seqbase_dst, seq); | |||||
| } | |||||
| } | |||||
| } | |||||
| static void seq_split_set_left_hold_offset(Sequence *seq, int timeline_frame) | static void seq_split_set_left_hold_offset(Sequence *seq, int timeline_frame) | ||||
| { | { | ||||
| /* Adjust within range of extended stillframes before strip. */ | /* Adjust within range of extended stillframes before strip. */ | ||||
| if (timeline_frame < seq->start) { | if (timeline_frame < seq->start) { | ||||
| seq->start = timeline_frame - 1; | seq->start = timeline_frame - 1; | ||||
| seq->anim_endofs += seq->len - 1; | seq->anim_endofs += seq->len - 1; | ||||
| seq->startstill = timeline_frame - seq->startdisp - 1; | seq->startstill = timeline_frame - seq->startdisp - 1; | ||||
| seq->endstill = 0; | seq->endstill = 0; | ||||
| ▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | static void seq_split_set_left_offset(Sequence *seq, int timeline_frame) | ||||
| /* Adjust within range of extended stillframes after strip. */ | /* Adjust within range of extended stillframes after strip. */ | ||||
| if ((seq->start + seq->len) < timeline_frame) { | if ((seq->start + seq->len) < timeline_frame) { | ||||
| seq->start = timeline_frame - seq->len + 1; | seq->start = timeline_frame - seq->len + 1; | ||||
| seq->endstill = seq->enddisp - timeline_frame - 1; | seq->endstill = seq->enddisp - timeline_frame - 1; | ||||
| } | } | ||||
| SEQ_transform_set_left_handle_frame(seq, timeline_frame); | SEQ_transform_set_left_handle_frame(seq, timeline_frame); | ||||
| } | } | ||||
| void seq_edit_split_handle_strip_offsets(Main *bmain, | |||||
| Scene *scene, | |||||
| Sequence *left_seq, | |||||
| Sequence *right_seq, | |||||
| const int timeline_frame, | |||||
| const eSeqSplitMethod method) | |||||
| { | |||||
| switch (method) { | |||||
| case SEQ_SPLIT_SOFT: | |||||
| seq_split_set_left_offset(right_seq, timeline_frame); | |||||
| seq_split_set_right_offset(left_seq, timeline_frame); | |||||
| break; | |||||
| case SEQ_SPLIT_HARD: | |||||
| seq_split_set_right_hold_offset(left_seq, timeline_frame); | |||||
| seq_split_set_left_hold_offset(right_seq, timeline_frame); | |||||
| SEQ_add_reload_new_file(bmain, scene, left_seq, false); | |||||
| SEQ_add_reload_new_file(bmain, scene, right_seq, false); | |||||
| break; | |||||
| } | |||||
| SEQ_time_update_sequence(scene, left_seq); | |||||
| SEQ_time_update_sequence(scene, right_seq); | |||||
| } | |||||
| /* Split multiple strip at once while maintaining relations between them. */ | |||||
| Sequence *seq_edit_split_chain(Main *bmain, | |||||
| Scene *scene, | |||||
| ListBase *seqbase, | |||||
| Sequence *seq, | |||||
| const int timeline_frame, | |||||
| const eSeqSplitMethod method) | |||||
| { | |||||
| ListBase left_strips = {NULL, NULL}; | |||||
| ListBase right_strips = {NULL, NULL}; | |||||
| seq_edit_move_chain_to_list_base(&left_strips, seqbase); | |||||
| SEQ_sequence_base_dupli_recursive( | |||||
| scene, scene, &right_strips, &left_strips, SEQ_DUPE_ANIM | SEQ_DUPE_ALL, 0); | |||||
| Sequence *left_seq = left_strips.first; | |||||
| Sequence *right_seq = right_strips.first; | |||||
| Sequence *return_seq = right_strips.first; | |||||
| while (left_seq && right_seq) { | |||||
| seq_edit_split_handle_strip_offsets(bmain, scene, left_seq, right_seq, timeline_frame, method); | |||||
| left_seq = left_seq->next; | |||||
| right_seq = right_seq->next; | |||||
| } | |||||
| /* Move right strips first, so left strips don't change name. */ | |||||
| BLI_movelisttolist(seqbase, &right_strips); | |||||
| BLI_movelisttolist(seqbase, &left_strips); | |||||
| LISTBASE_FOREACH (Sequence *, seq, seqbase) { | |||||
| SEQ_iterator_recursive_apply(seq, SEQ_iterator_apply_unique_name_fn, scene); | |||||
| } | |||||
| seq_edit_clear_chain_tag(seqbase); | |||||
| return return_seq; | |||||
| } | |||||
| /** | /** | ||||
| * Split Sequence at timeline_frame in two. | * Split Sequence at timeline_frame in two. | ||||
| * | * | ||||
| * \param bmain: Main in which Sequence is located | * \param bmain: Main in which Sequence is located | ||||
| * \param scene: Scene in which Sequence is located | * \param scene: Scene in which Sequence is located | ||||
| * \param seqbase: ListBase in which Sequence is located | * \param seqbase: ListBase in which Sequence is located | ||||
| * \param seq: Sequence to be split | * \param seq: Sequence to be split | ||||
| * \param timeline_frame: frame at which seq is split. | * \param timeline_frame: frame at which seq is split. | ||||
| * \param method: affects type of offset to be applied to resize Sequence | * \param method: affects type of offset to be applied to resize Sequence | ||||
| * \return The newly created sequence strip. This is always Sequence on right side. | * \return The newly created sequence strip. This is always Sequence on right side. | ||||
| */ | */ | ||||
| Sequence *SEQ_edit_strip_split(Main *bmain, | Sequence *SEQ_edit_strip_split(Main *bmain, | ||||
| Scene *scene, | Scene *scene, | ||||
| ListBase *seqbase, | ListBase *seqbase, | ||||
| Sequence *seq, | Sequence *seq, | ||||
| const int timeline_frame, | const int timeline_frame, | ||||
| const eSeqSplitMethod method) | const eSeqSplitMethod method) | ||||
| { | { | ||||
| if (timeline_frame <= seq->startdisp || timeline_frame >= seq->enddisp) { | if (timeline_frame <= seq->startdisp || timeline_frame >= seq->enddisp) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| Sequence *left_seq; | |||||
| Sequence *right_seq; | |||||
| const int chain_strip_count = seq_edit_tag_chain(seq, seqbase); | |||||
| if (chain_strip_count > 1) { | |||||
| if (method == SEQ_SPLIT_HARD) { | |||||
| LISTBASE_FOREACH (Sequence *, seq, seqbase) { | |||||
| if (seq->flag & SEQ_FLAG_CHAIN_TAG) { | |||||
| /* Precaution, needed because the length saved on-disk may not match the length saved in | |||||
| * the blend file, or our code may have minor differences reading file length between | |||||
| * versions. This causes hard-split to fail, see: T47862. */ | |||||
| SEQ_add_reload_new_file(bmain, scene, seq, true); | |||||
| SEQ_time_update_sequence(scene, seq); | |||||
| } | |||||
| } | |||||
| } | |||||
| right_seq = seq_edit_split_chain(bmain, scene, seqbase, seq, timeline_frame, method); | |||||
| } | |||||
| else { | |||||
| if (method == SEQ_SPLIT_HARD) { | if (method == SEQ_SPLIT_HARD) { | ||||
| /* Precaution, needed because the length saved on-disk may not match the length saved in the | /* Precaution, needed because the length saved on-disk may not match the length saved in the | ||||
| * blend file, or our code may have minor differences reading file length between versions. | * blend file, or our code may have minor differences reading file length between versions. | ||||
| * This causes hard-split to fail, see: T47862. */ | * This causes hard-split to fail, see: T47862. */ | ||||
| SEQ_add_reload_new_file(bmain, scene, seq, true); | SEQ_add_reload_new_file(bmain, scene, seq, true); | ||||
| SEQ_time_update_sequence(scene, seq); | SEQ_time_update_sequence(scene, seq); | ||||
| } | } | ||||
| Sequence *left_seq = seq; | left_seq = seq; | ||||
| Sequence *right_seq = SEQ_sequence_dupli_recursive( | right_seq = SEQ_sequence_dupli_recursive( | ||||
| scene, scene, seqbase, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM); | scene, scene, seqbase, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM); | ||||
| seq_edit_split_handle_strip_offsets(bmain, scene, left_seq, right_seq, timeline_frame, method); | |||||
sergey: Declaration of `seq` here shadows a parameter. | |||||
| switch (method) { | |||||
| case SEQ_SPLIT_SOFT: | |||||
| seq_split_set_left_offset(right_seq, timeline_frame); | |||||
| seq_split_set_right_offset(left_seq, timeline_frame); | |||||
| break; | |||||
| case SEQ_SPLIT_HARD: | |||||
| seq_split_set_right_hold_offset(left_seq, timeline_frame); | |||||
| seq_split_set_left_hold_offset(right_seq, timeline_frame); | |||||
| SEQ_add_reload_new_file(bmain, scene, left_seq, false); | |||||
| SEQ_add_reload_new_file(bmain, scene, right_seq, false); | |||||
| break; | |||||
| } | } | ||||
| SEQ_time_update_sequence(scene, left_seq); | |||||
| SEQ_time_update_sequence(scene, right_seq); | seq_edit_clear_chain_tag(seqbase); | ||||
| return right_seq; | return right_seq; | ||||
| } | } | ||||
| /** | /** | ||||
| * Find gap after initial_frame and move strips on right side to close the gap | * Find gap after initial_frame and move strips on right side to close the gap | ||||
| * | * | ||||
| * \param scene: Scene in which strips are located | * \param scene: Scene in which strips are located | ||||
| * \param seqbase: ListBase in which strips are located | * \param seqbase: ListBase in which strips are located | ||||
| Show All 29 Lines | |||||
Declaration of seq here shadows a parameter.