Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Antalik <richardantalik@gmail.com>2021-08-27 13:59:46 +0300
committerRichard Antalik <richardantalik@gmail.com>2021-08-27 13:59:46 +0300
commit59cd9c6da682675c439731781d127b1b02f12a76 (patch)
treebe3547652d6e9bf2e4051dbd54a71b771ec5afad /source/blender/editors
parent7f7370fa26fbe8597cbb9832755f854fd4a8d0e5 (diff)
VSE: Transform overwrite mode
Add mode to overwrite strips on overlap instead of resolving overlap. When overlap is created, 3 things can happen: - On partial overlap, handles of overlapped strip are moved - On complete overlap with smaller strip, overlapped strip is split - On complete overlap with larger strip, overlapped strip is removed This mode can be enabled in header. Reviewed By: fsiddi, mano-wii Differential Revision: https://developer.blender.org/D11805
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c9
-rw-r--r--source/blender/editors/transform/transform_convert_sequencer.c220
-rw-r--r--source/blender/editors/transform/transform_mode_edge_seq_slide.c25
3 files changed, 197 insertions, 57 deletions
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index b3c39e2fa6f..fe3ff469e50 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -737,7 +737,8 @@ static void draw_seq_handle(View2D *v2d,
}
}
-static void draw_seq_outline(Sequence *seq,
+static void draw_seq_outline(Scene *scene,
+ Sequence *seq,
uint pos,
float x1,
float x2,
@@ -765,7 +766,9 @@ static void draw_seq_outline(Sequence *seq,
* - Slightly lighter.
* - Red when overlapping with other strips.
*/
- if ((G.moving & G_TRANSFORM_SEQ) && (seq->flag & SELECT)) {
+ const eSeqOverlapMode overlap_mode = SEQ_tool_settings_overlap_mode_get(scene);
+ if ((G.moving & G_TRANSFORM_SEQ) && (seq->flag & SELECT) &&
+ overlap_mode != SEQ_OVERLAP_OVERWRITE) {
if (seq->flag & SEQ_OVERLAP) {
col[0] = 255;
col[1] = col[2] = 33;
@@ -1383,7 +1386,7 @@ static void draw_seq_strip(const bContext *C,
v2d, seq, handsize_clamped, SEQ_RIGHTHANDLE, pos, seq_active, pixelx, y_threshold);
}
- draw_seq_outline(seq, pos, x1, x2, y1, y2, pixelx, pixely, seq_active);
+ draw_seq_outline(scene, seq, pos, x1, x2, y1, y2, pixelx, pixely, seq_active);
immUnbindProgram();
diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c
index 45ed0f3b664..9548498f0b8 100644
--- a/source/blender/editors/transform/transform_convert_sequencer.c
+++ b/source/blender/editors/transform/transform_convert_sequencer.c
@@ -29,10 +29,13 @@
#include "BLI_math.h"
#include "BKE_context.h"
+#include "BKE_main.h"
#include "BKE_report.h"
#include "ED_markers.h"
+#include "SEQ_edit.h"
+#include "SEQ_effects.h"
#include "SEQ_iterator.h"
#include "SEQ_relations.h"
#include "SEQ_sequencer.h"
@@ -341,12 +344,17 @@ static bool seq_transform_check_strip_effects(SeqCollection *transformed_strips)
return false;
}
+static ListBase *seqbase_active_get(const TransInfo *t)
+{
+ Editing *ed = SEQ_editing_get(t->scene, false);
+ return SEQ_active_seqbase_get(ed);
+}
+
/* Offset all strips positioned after left edge of transformed strips boundbox by amount equal
* to overlap of transformed strips. */
static void seq_transform_handle_expand_to_fit(TransInfo *t, SeqCollection *transformed_strips)
{
- Editing *ed = SEQ_editing_get(t->scene, false);
- ListBase *seqbasep = SEQ_active_seqbase_get(ed);
+ ListBase *seqbasep = seqbase_active_get(t);
ListBase *markers = &t->scene->markers;
const bool use_sync_markers = (((SpaceSeq *)t->area->spacedata.first)->flag &
SEQ_MARKER_TRANS) != 0;
@@ -378,23 +386,178 @@ static void seq_transform_handle_expand_to_fit(TransInfo *t, SeqCollection *tran
SEQ_collection_free(right_side_strips);
}
-static void seq_transform_handle_overlap(TransInfo *t, SeqCollection *transformed_strips)
+static SeqCollection *query_overwrite_targets(const TransInfo *t,
+ SeqCollection *transformed_strips)
{
- Editing *ed = SEQ_editing_get(t->scene, false);
- ListBase *seqbasep = SEQ_active_seqbase_get(ed);
+ SeqCollection *collection = SEQ_query_unselected_strips(seqbase_active_get(t));
+
+ Sequence *seq, *seq_transformed;
+ SEQ_ITERATOR_FOREACH (seq, collection) {
+ bool does_overlap = false;
- if (t->flag & T_ALT_TRANSFORM) {
- seq_transform_handle_expand_to_fit(t, transformed_strips);
+ SEQ_ITERATOR_FOREACH (seq_transformed, transformed_strips) {
+ /* Effects of transformed strips can be unselected. These must not be included. */
+ if (seq == seq_transformed) {
+ SEQ_collection_remove_strip(seq, collection);
+ }
+ if (SEQ_transform_test_overlap_seq_seq(seq, seq_transformed)) {
+ does_overlap = true;
+ }
+ }
+
+ if (!does_overlap) {
+ SEQ_collection_remove_strip(seq, collection);
+ }
}
- else {
- ListBase *markers = &t->scene->markers;
- const bool use_sync_markers = (((SpaceSeq *)t->area->spacedata.first)->flag &
- SEQ_MARKER_TRANS) != 0;
- /* Shuffle non strips with no effects attached. */
- SeqCollection *standalone_strips = extract_standalone_strips(transformed_strips);
- SEQ_transform_seqbase_shuffle_time(
- standalone_strips, seqbasep, t->scene, markers, use_sync_markers);
- SEQ_collection_free(standalone_strips);
+
+ return collection;
+}
+
+typedef enum eOvelapDescrition {
+ /* No overlap. */
+ STRIP_OVERLAP_NONE,
+ /* Overlapping strip covers overlapped completely. */
+ STRIP_OVERLAP_IS_FULL,
+ /* Overlapping strip is inside overlapped. */
+ STRIP_OVERLAP_IS_INSIDE,
+ /* Partial overlap between 2 strips. */
+ STRIP_OVERLAP_LEFT_SIDE,
+ STRIP_OVERLAP_RIGHT_SIDE,
+} eOvelapDescrition;
+
+static eOvelapDescrition overlap_description_get(const Sequence *transformed,
+ const Sequence *target)
+{
+ if (transformed->startdisp <= target->startdisp && transformed->enddisp >= target->enddisp) {
+ return STRIP_OVERLAP_IS_FULL;
+ }
+ if (transformed->startdisp > target->startdisp && transformed->enddisp < target->enddisp) {
+ return STRIP_OVERLAP_IS_INSIDE;
+ }
+ if (transformed->startdisp <= target->startdisp && target->startdisp <= transformed->enddisp) {
+ return STRIP_OVERLAP_LEFT_SIDE;
+ }
+ if (transformed->startdisp <= target->enddisp && target->enddisp <= transformed->enddisp) {
+ return STRIP_OVERLAP_RIGHT_SIDE;
+ }
+ return STRIP_OVERLAP_NONE;
+}
+
+/* Split strip in 3 parts, remove middle part and fit transformed inside. */
+static void seq_transform_handle_overwrite_split(const TransInfo *t,
+ const Sequence *transformed,
+ Sequence *target)
+{
+ Main *bmain = CTX_data_main(t->context);
+ Scene *scene = t->scene;
+ ListBase *seqbase = seqbase_active_get(t);
+
+ Sequence *split_strip = SEQ_edit_strip_split(
+ bmain, scene, seqbase, target, transformed->startdisp, SEQ_SPLIT_SOFT, NULL);
+ SEQ_edit_strip_split(
+ bmain, scene, seqbase, split_strip, transformed->enddisp, SEQ_SPLIT_SOFT, NULL);
+ SEQ_edit_flag_for_removal(scene, seqbase_active_get(t), split_strip);
+}
+
+/* Trim strips by adjusting handle position.
+ * This is bit more complicated in case overlap happens on effect. */
+static void seq_transform_handle_overwrite_trim(const TransInfo *t,
+ const Sequence *transformed,
+ Sequence *target,
+ const eOvelapDescrition overlap)
+{
+ SeqCollection *targets = SEQ_query_by_reference(
+ target, seqbase_active_get(t), SEQ_query_strip_effect_chain);
+
+ /* Expand collection by adding all target's children, effects and their children. */
+ if ((target->type & SEQ_TYPE_EFFECT) != 0) {
+ SEQ_collection_expand(seqbase_active_get(t), targets, SEQ_query_strip_effect_chain);
+ }
+
+ /* Trim all non effects, that have influence on effect length which is overlapping. */
+ Sequence *seq;
+ SEQ_ITERATOR_FOREACH (seq, targets) {
+ if ((seq->type & SEQ_TYPE_EFFECT) != 0 && SEQ_effect_get_num_inputs(seq->type) > 0) {
+ continue;
+ }
+ if (overlap == STRIP_OVERLAP_LEFT_SIDE) {
+ SEQ_transform_set_left_handle_frame(seq, transformed->enddisp);
+ }
+ else {
+ BLI_assert(overlap == STRIP_OVERLAP_RIGHT_SIDE);
+ SEQ_transform_set_right_handle_frame(seq, transformed->startdisp);
+ }
+ SEQ_time_update_sequence(t->scene, seq);
+ }
+ SEQ_collection_free(targets);
+}
+
+static void seq_transform_handle_overwrite(const TransInfo *t, SeqCollection *transformed_strips)
+{
+ SeqCollection *targets = query_overwrite_targets(t, transformed_strips);
+
+ bool strips_delete = false;
+ Sequence *target;
+ Sequence *transformed;
+ SEQ_ITERATOR_FOREACH (target, targets) {
+ SEQ_ITERATOR_FOREACH (transformed, transformed_strips) {
+ if (transformed->machine != target->machine) {
+ continue;
+ }
+
+ const eOvelapDescrition overlap = overlap_description_get(transformed, target);
+
+ if (overlap == STRIP_OVERLAP_IS_FULL) {
+ /* Remove covered strip. */
+ SEQ_edit_flag_for_removal(t->scene, seqbase_active_get(t), target);
+ strips_delete = true;
+ }
+ else if (overlap == STRIP_OVERLAP_IS_INSIDE) {
+ seq_transform_handle_overwrite_split(t, transformed, target);
+ strips_delete = true;
+ }
+ else if (ELEM(overlap, STRIP_OVERLAP_LEFT_SIDE, STRIP_OVERLAP_RIGHT_SIDE)) {
+ seq_transform_handle_overwrite_trim(t, transformed, target, overlap);
+ }
+ }
+ }
+
+ SEQ_collection_free(targets);
+
+ if (strips_delete) {
+ SEQ_edit_remove_flagged_sequences(t->scene, seqbase_active_get(t));
+ }
+}
+
+static void seq_transform_handle_overlap_shuffle(const TransInfo *t,
+ SeqCollection *transformed_strips)
+{
+ ListBase *seqbase = seqbase_active_get(t);
+ ListBase *markers = &t->scene->markers;
+ const bool use_sync_markers = (((SpaceSeq *)t->area->spacedata.first)->flag &
+ SEQ_MARKER_TRANS) != 0;
+ /* Shuffle non strips with no effects attached. */
+ SeqCollection *standalone_strips = extract_standalone_strips(transformed_strips);
+ SEQ_transform_seqbase_shuffle_time(
+ standalone_strips, seqbase, t->scene, markers, use_sync_markers);
+ SEQ_collection_free(standalone_strips);
+}
+
+static void seq_transform_handle_overlap(TransInfo *t, SeqCollection *transformed_strips)
+{
+ ListBase *seqbasep = seqbase_active_get(t);
+ const eSeqOverlapMode overlap_mode = SEQ_tool_settings_overlap_mode_get(t->scene);
+
+ switch (overlap_mode) {
+ case SEQ_OVERLAP_EXPAND:
+ seq_transform_handle_expand_to_fit(t, transformed_strips);
+ break;
+ case SEQ_OVERLAP_OVERWRITE:
+ seq_transform_handle_overwrite(t, transformed_strips);
+ break;
+ case SEQ_OVERLAP_SHUFFLE:
+ seq_transform_handle_overlap_shuffle(t, transformed_strips);
+ break;
}
if (seq_transform_check_strip_effects(transformed_strips)) {
@@ -409,6 +572,7 @@ static void seq_transform_handle_overlap(TransInfo *t, SeqCollection *transforme
if (SEQ_transform_test_overlap(seqbasep, seq)) {
SEQ_transform_seqbase_shuffle(seqbasep, seq, t->scene);
}
+ seq->flag &= ~SEQ_OVERLAP;
}
}
@@ -432,6 +596,7 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c
}
SeqCollection *transformed_strips = seq_transform_collection_from_transdata(tc);
+ SEQ_collection_expand(seqbase_active_get(t), transformed_strips, SEQ_query_strip_effect_chain);
if (t->state == TRANS_CANCEL) {
seq_transform_cancel(t, transformed_strips);
@@ -549,7 +714,7 @@ BLI_INLINE void trans_update_seq(Scene *sce, Sequence *seq, int old_start, int s
static void flushTransSeq(TransInfo *t)
{
/* Editing null check already done */
- ListBase *seqbasep = SEQ_editing_get(t->scene, false)->seqbasep;
+ ListBase *seqbasep = seqbase_active_get(t);
int a, new_frame;
TransData *td = NULL;
@@ -601,22 +766,17 @@ static void flushTransSeq(TransInfo *t)
/* need to do the overlap check in a new loop otherwise adjacent strips
* will not be updated and we'll get false positives */
- Sequence *seq_prev = NULL;
- seq_prev = NULL;
- for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) {
-
- tdsq = (TransDataSeq *)td->extra;
- seq = tdsq->seq;
+ SeqCollection *transformed_strips = seq_transform_collection_from_transdata(tc);
+ SEQ_collection_expand(seqbase_active_get(t), transformed_strips, SEQ_query_strip_effect_chain);
- if (seq != seq_prev) {
- /* test overlap, displays red outline */
- seq->flag &= ~SEQ_OVERLAP;
- if (SEQ_transform_test_overlap(seqbasep, seq)) {
- seq->flag |= SEQ_OVERLAP;
- }
+ SEQ_ITERATOR_FOREACH (seq, transformed_strips) {
+ /* test overlap, displays red outline */
+ seq->flag &= ~SEQ_OVERLAP;
+ if (SEQ_transform_test_overlap(seqbasep, seq)) {
+ seq->flag |= SEQ_OVERLAP;
}
- seq_prev = seq;
}
+ SEQ_collection_free(transformed_strips);
}
/* helper for recalcData() - for sequencer transforms */
diff --git a/source/blender/editors/transform/transform_mode_edge_seq_slide.c b/source/blender/editors/transform/transform_mode_edge_seq_slide.c
index a8f7fc43b5e..fb70d04a530 100644
--- a/source/blender/editors/transform/transform_mode_edge_seq_slide.c
+++ b/source/blender/editors/transform/transform_mode_edge_seq_slide.c
@@ -54,18 +54,6 @@
/** \name Transform (Sequencer Slide)
* \{ */
-static eRedrawFlag seq_slide_handleEvent(struct TransInfo *t, const wmEvent *event)
-{
- BLI_assert(t->mode == TFM_SEQ_SLIDE);
- const wmKeyMapItem *kmi = t->custom.mode.data;
- if (kmi && event->type == kmi->type && event->val == kmi->val) {
- /* Allows the "Expand to Fit" effect to be enabled as a toggle. */
- t->flag ^= T_ALT_TRANSFORM;
- return TREDRAW_HARD;
- }
- return TREDRAW_NOTHING;
-}
-
static void headerSeqSlide(TransInfo *t, const float val[2], char str[UI_MAX_DRAW_STR])
{
char tvec[NUM_STR_REP_LEN * 3];
@@ -79,17 +67,7 @@ static void headerSeqSlide(TransInfo *t, const float val[2], char str[UI_MAX_DRA
}
ofs += BLI_snprintf_rlen(
- str + ofs, UI_MAX_DRAW_STR - ofs, TIP_("Sequence Slide: %s%s, ("), &tvec[0], t->con.text);
-
- const wmKeyMapItem *kmi = t->custom.mode.data;
- if (kmi) {
- ofs += WM_keymap_item_to_string(kmi, false, str + ofs, UI_MAX_DRAW_STR - ofs);
- }
-
- ofs += BLI_snprintf_rlen(str + ofs,
- UI_MAX_DRAW_STR - ofs,
- TIP_(" or Alt) Expand to fit %s"),
- WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0));
+ str + ofs, UI_MAX_DRAW_STR - ofs, TIP_("Sequence Slide: %s%s"), &tvec[0], t->con.text);
}
static void applySeqSlideValue(TransInfo *t, const float val[2])
@@ -148,7 +126,6 @@ static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2]))
void initSeqSlide(TransInfo *t)
{
t->transform = applySeqSlide;
- t->handleEvent = seq_slide_handleEvent;
t->tsnap.applySnap = transform_snap_sequencer_apply_translate;
initMouseInputMode(t, &t->mouse, INPUT_VECTOR);