[Bf-blender-cvs] [662b6f0ffac] temp-vse-transform-overwrite: [WIP] VSE: Transform overwrite mode

Richard Antalik noreply at git.blender.org
Sat Jul 17 03:25:36 CEST 2021


Commit: 662b6f0ffac8623bd8e794c0b03985d2133df217
Author: Richard Antalik
Date:   Fri Jul 16 23:50:35 2021 +0200
Branches: temp-vse-transform-overwrite
https://developer.blender.org/rB662b6f0ffac8623bd8e794c0b03985d2133df217

[WIP] VSE: Transform overwrite mode

WIP status: logic is implemented, and overwrite mode is currently forced.

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

There are some edge cases where this mode may not work very well, this
is mainly case for partial overlap with effects. This situation can be
resolved in more than one way and I don't think it can be predicted.

Differential Revision: https://developer.blender.org/D11805

===================================================================

M	source/blender/editors/transform/transform_convert_sequencer.c
M	source/blender/editors/transform/transform_snap_sequencer.c
M	source/blender/sequencer/SEQ_iterator.h
M	source/blender/sequencer/intern/iterator.c

===================================================================

diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c
index 17512c79d03..4f8ac7d75da 100644
--- a/source/blender/editors/transform/transform_convert_sequencer.c
+++ b/source/blender/editors/transform/transform_convert_sequencer.c
@@ -27,12 +27,15 @@
 
 #include "BLI_listbase.h"
 #include "BLI_math.h"
+#include "BLI_rect.h"
 
 #include "BKE_context.h"
+#include "BKE_main.h"
 #include "BKE_report.h"
 
 #include "ED_markers.h"
 
+#include "SEQ_edit.h"
 #include "SEQ_iterator.h"
 #include "SEQ_relations.h"
 #include "SEQ_sequencer.h"
@@ -299,7 +302,20 @@ static SeqCollection *extract_standalone_strips(SeqCollection *transformed_strip
   return collection;
 }
 
-/* Query strips positioned after left edge of transformed strips boundbox. */
+static void seq_collection_boundbox(SeqCollection *collection, rcti *r_boundbox)
+{
+  BLI_rcti_init(r_boundbox, MAXFRAME, MINFRAME, INT_MAX, 0);
+
+  Sequence *seq;
+  SEQ_ITERATOR_FOREACH (seq, collection) {
+    r_boundbox->xmin = min_ii(r_boundbox->xmin, seq->startdisp);
+    r_boundbox->xmax = max_ii(r_boundbox->xmax, seq->enddisp);
+    r_boundbox->ymin = min_ii(r_boundbox->ymin, seq->machine);
+    r_boundbox->ymax = max_ii(r_boundbox->ymax, seq->machine);
+  }
+}
+
+/* Query strips positioned after left edge of transformed strips r_boundbox. */
 static SeqCollection *query_right_side_strips(ListBase *seqbase, SeqCollection *transformed_strips)
 {
   int minframe = MAXFRAME;
@@ -341,12 +357,17 @@ static bool seq_transform_check_strip_effects(SeqCollection *transformed_strips)
   return false;
 }
 
-/* Offset all strips positioned after left edge of transformed strips boundbox by amount equal
+static ListBase *seqbase_from_trans_info(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 r_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_from_trans_info(t);
   ListBase *markers = &t->scene->markers;
   const bool use_sync_markers = (((SpaceSeq *)t->area->spacedata.first)->flag &
                                  SEQ_MARKER_TRANS) != 0;
@@ -378,15 +399,181 @@ static void seq_transform_handle_expand_to_fit(TransInfo *t, SeqCollection *tran
   SEQ_collection_free(right_side_strips);
 }
 
+static SeqCollection *query_overwrite_targets(TransInfo *t, SeqCollection *transformed_strips)
+{
+  rcti transformed_boundbox;
+  seq_collection_boundbox(transformed_strips, &transformed_boundbox);
+  SeqCollection *collection = SEQ_query_unselected_strips(seqbase_from_trans_info(t));
+
+  Sequence *seq;
+  SEQ_ITERATOR_FOREACH (seq, collection) {
+    if (seq->enddisp < transformed_boundbox.xmin || seq->startdisp > transformed_boundbox.xmax) {
+      SEQ_collection_remove_strip(seq, collection);
+    }
+  }
+
+  /* In some cases effects of transformed strips are not selected. These must not be included. */
+  SEQ_ITERATOR_FOREACH (seq, transformed_strips) {
+    SEQ_collection_remove_strip(seq, collection);
+  }
+
+  return collection;
+}
+
+static bool is_same_channel(Sequence *transformed, Sequence *target)
+{
+  if (transformed->machine == target->machine) {
+    return true;
+  }
+  return false;
+}
+
+static bool is_full_overlap(Sequence *transformed, Sequence *target)
+{
+  if (transformed->startdisp <= target->startdisp && transformed->enddisp >= target->enddisp) {
+    return true;
+  }
+  return false;
+}
+
+static bool is_inside_overlap(Sequence *transformed, Sequence *target)
+{
+  if (transformed->startdisp > target->startdisp && transformed->enddisp < target->enddisp) {
+    return true;
+  }
+  return false;
+}
+
+typedef enum ePartialOvelapSide {
+  LEFT_SIDE_OVERLAP,
+  RIGHT_SIDE_OVERLAP,
+} ePartialOvelapSide;
+
+static bool is_partial_overlap(Sequence *transformed, Sequence *target, ePartialOvelapSide *r_side)
+{
+  if (transformed->startdisp <= target->startdisp && target->startdisp <= transformed->enddisp) {
+    *r_side = LEFT_SIDE_OVERLAP;
+    return true;
+  }
+  if (transformed->startdisp <= target->enddisp && target->enddisp <= transformed->enddisp) {
+    *r_side = RIGHT_SIDE_OVERLAP;
+    return true;
+  }
+  return false;
+}
+
+static void seq_transform_handle_overwrite_split(TransInfo *t,
+                                                 Sequence *transformed,
+                                                 Sequence *target)
+{
+  Main *bmain = CTX_data_main(t->context);
+  Scene *scene = t->scene;
+  ListBase *seqbase = seqbase_from_trans_info(t);
+
+  Sequence *split_strip = SEQ_edit_strip_split(
+      bmain, scene, seqbase, target, transformed->startdisp, SEQ_SPLIT_SOFT);
+  SEQ_edit_strip_split(bmain, scene, seqbase, split_strip, transformed->enddisp, SEQ_SPLIT_SOFT);
+  SEQ_edit_flag_for_removal(scene, seqbase_from_trans_info(t), split_strip);
+}
+
+/* BUG must handle overlap with non-effect more gracefully. */
+
+/* Trim strips by adjusting handle position.
+ * This is bit more complicated in case overlap happens on effect. */
+static void seq_transform_handle_overwrite_trim(TransInfo *t,
+                                                Sequence *transformed,
+                                                Sequence *target,
+                                                ePartialOvelapSide overlap_side)
+{
+  SeqCollection *targets = SEQ_collection_create(__func__);
+  SEQ_collection_append_strip(target, targets);
+
+  /* Expand collection by adding all target's children, effects and their children. */
+  if ((target->type & SEQ_TYPE_EFFECT) != 0) {
+    SEQ_collection_expand(seqbase_from_trans_info(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) {
+      continue;
+    }
+    if (is_partial_overlap(transformed, seq, &overlap_side)) {
+      if (overlap_side == LEFT_SIDE_OVERLAP) {
+        SEQ_transform_set_left_handle_frame(seq, transformed->enddisp);
+      }
+      if (overlap_side == RIGHT_SIDE_OVERLAP) {
+        SEQ_transform_set_right_handle_frame(seq, transformed->startdisp);
+      }
+    }
+    SEQ_time_update_sequence(t->scene, seq);
+  }
+
+  SEQ_collection_free(targets);
+
+  /* Recalculate all effects influenced by target. */
+  SeqCollection *effects = SEQ_query_by_reference(target, seqbase_from_trans_info(t), SEQ_query_strip_effect_chain);
+  SEQ_ITERATOR_FOREACH (seq, effects) {
+    SEQ_time_update_sequence(t->scene, seq);
+  }
+  SEQ_collection_free(effects);
+}
+
+static void seq_transform_handle_overwrite(TransInfo *t, SeqCollection *transformed_strips)
+{
+  SeqCollection *targets = query_overwrite_targets(t, transformed_strips);
+
+  ePartialOvelapSide overlap_side;
+  bool strips_delete = false;
+  Sequence *target;
+  Sequence *transformed;
+  SEQ_ITERATOR_FOREACH (target, targets) {
+    SEQ_ITERATOR_FOREACH (transformed, transformed_strips) {
+      if (!is_same_channel(transformed, target)) {
+        continue;
+      }
+
+      /* Remove covered strip. */
+      if (is_full_overlap(transformed, target)) {
+        SEQ_edit_flag_for_removal(t->scene, seqbase_from_trans_info(t), target);
+        strips_delete = true;
+      }
+      /* Split strip in 3 parts, remove middle part and fit transformed inside. */
+      else if (is_inside_overlap(transformed, target)) {
+        seq_transform_handle_overwrite_split(t, transformed, target);
+        strips_delete = true;
+      }
+      /* Nove handle by amount of overlap. */
+      else if (is_partial_overlap(transformed, target, &overlap_side)) {
+        seq_transform_handle_overwrite_trim(t, transformed, target, overlap_side);
+      }
+    }
+  }
+
+  SEQ_collection_free(targets);
+
+  if (strips_delete) {
+    SEQ_edit_remove_flagged_sequences(t->scene, seqbase_from_trans_info(t));
+  }
+}
+
 static void seq_transform_handle_overlap(TransInfo *t, SeqCollection *transformed_strips)
 {
-  Editing *ed = SEQ_editing_get(t->scene, false);
-  ListBase *seqbasep = SEQ_active_seqbase_get(ed);
+  ListBase *seqbasep = seqbase_from_trans_info(t);
+
+  /* Modes */
+  const bool overwrite = true;
+  const bool default_mode = false;
+  const bool expand = t->flag & T_ALT_TRANSFORM;
 
-  if (t->flag & T_ALT_TRANSFORM) {
+  if (expand) {
     seq_transform_handle_expand_to_fit(t, transformed_strips);
   }
-  else {
+  else if (overwrite) {
+    seq_transform_handle_overwrite(t, transformed_strips);
+  }
+  else if (default_mode) {
     ListBase *markers = &t->scene->markers;
     const bool use_sync_markers = (((SpaceSeq *)t->area->spacedata.first)->flag &
                                    SEQ_MARKER_TRANS) != 0;
@@ -433,6 +620,8 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c
   }
 
   SeqCollection *transformed_strips = seq_transform_collection_from_transdata(tc);
+  SEQ_collection_expand(
+      seqbase_from_trans_info(t), transformed_strips, SEQ_query_strip_effect_chain);
 
   if (t->state == TRANS_CANCEL) {
     seq_transform_cancel(t, transformed_strips);
@@ -550,7 +739,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_from_trans_info(t);
 
   int a, new_frame;
   TransData *td = NULL;
@@ -602,22 +791,18 @@ 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_str

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list