Blender  V3.3
strip_transform.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved.
3  * 2003-2009 Blender Foundation.
4  * 2005-2006 Peter Schlaile <peter [at] schlaile [dot] de> */
5 
10 #include "DNA_scene_types.h"
11 #include "DNA_sequence_types.h"
12 
13 #include "BLI_listbase.h"
14 #include "BLI_math.h"
15 
16 #include "BKE_main.h"
17 #include "BKE_scene.h"
18 #include "BKE_sound.h"
19 
20 #include "SEQ_animation.h"
21 #include "SEQ_channels.h"
22 #include "SEQ_edit.h"
23 #include "SEQ_effects.h"
24 #include "SEQ_iterator.h"
25 #include "SEQ_relations.h"
26 #include "SEQ_sequencer.h"
27 #include "SEQ_time.h"
28 #include "SEQ_transform.h"
29 
30 #include "sequencer.h"
31 #include "strip_time.h"
32 
33 #include "CLG_log.h"
34 
35 static CLG_LogRef LOG = {"seq.strip_transform"};
36 
38 {
39  return ((seq->len == 1) &&
40  (seq->type == SEQ_TYPE_IMAGE ||
41  ((seq->type & SEQ_TYPE_EFFECT) && SEQ_effect_get_num_inputs(seq->type) == 0)));
42 }
43 
45 {
46  Sequence *seq;
47  /* is there more than 1 select */
48  bool ok = false;
49 
50  for (seq = seqbase->first; seq; seq = seq->next) {
51  if (seq->flag & SELECT) {
52  ok = true;
53  break;
54  }
55  }
56 
57  if (ok == false) {
58  return false;
59  }
60 
61  /* test relationships */
62  for (seq = seqbase->first; seq; seq = seq->next) {
63  if ((seq->type & SEQ_TYPE_EFFECT) == 0) {
64  continue;
65  }
66 
67  if (seq->flag & SELECT) {
68  if ((seq->seq1 && (seq->seq1->flag & SELECT) == 0) ||
69  (seq->seq2 && (seq->seq2->flag & SELECT) == 0) ||
70  (seq->seq3 && (seq->seq3->flag & SELECT) == 0)) {
71  return false;
72  }
73  }
74  else {
75  if ((seq->seq1 && (seq->seq1->flag & SELECT)) || (seq->seq2 && (seq->seq2->flag & SELECT)) ||
76  (seq->seq3 && (seq->seq3->flag & SELECT))) {
77  return false;
78  }
79  }
80  }
81 
82  return true;
83 }
84 
86 {
87  int left, start, offset;
89  return;
90  }
91 
92  /* make sure the image is always at the start since there is only one,
93  * adjusting its start should be ok */
95  start = seq->start;
96  if (start != left) {
97  offset = left - start;
102  seq->start += offset;
103  }
104 }
105 
107 {
108  return !(seq->type & SEQ_TYPE_EFFECT) || (SEQ_effect_get_num_inputs(seq->type) == 0);
109 }
110 
112 {
113  return (seq1 != seq2 && seq1->machine == seq2->machine &&
117  SEQ_time_right_handle_frame_get(scene, seq2))) == 0);
118 }
119 
121 {
122  Sequence *seq;
123 
124  seq = seqbasep->first;
125  while (seq) {
126  if (SEQ_transform_test_overlap_seq_seq(scene, test, seq)) {
127  return true;
128  }
129 
130  seq = seq->next;
131  }
132  return false;
133 }
134 
135 void SEQ_transform_translate_sequence(Scene *evil_scene, Sequence *seq, int delta)
136 {
137  if (delta == 0) {
138  return;
139  }
140 
141  /* Meta strips requires their content is to be translated, and then frame range of the meta is
142  * updated based on nested strips. Thiw won't work for empty metas, so they can be treated as
143  * normal strip. */
144  if (seq->type == SEQ_TYPE_META && !BLI_listbase_is_empty(&seq->seqbase)) {
145  Sequence *seq_child;
146  for (seq_child = seq->seqbase.first; seq_child; seq_child = seq_child->next) {
147  SEQ_transform_translate_sequence(evil_scene, seq_child, delta);
148  }
149  /* Move meta start/end points. */
150  seq_time_translate_handles(evil_scene, seq, delta);
151  }
152  else { /* All other strip types. */
153  seq->start += delta;
154  /* Only to make files usable in older versions. */
155  seq->startdisp = SEQ_time_left_handle_frame_get(evil_scene, seq);
156  seq->enddisp = SEQ_time_right_handle_frame_get(evil_scene, seq);
157  }
158 
159  SEQ_offset_animdata(evil_scene, seq, delta);
162  seq_sequence_lookup_effects_by_seq(evil_scene, seq));
163 }
164 
166  Sequence *test,
167  Scene *evil_scene,
168  int channel_delta)
169 {
170  const int orig_machine = test->machine;
171  BLI_assert(ELEM(channel_delta, -1, 1));
172 
173  test->machine += channel_delta;
174  while (SEQ_transform_test_overlap(evil_scene, seqbasep, test)) {
175  if ((channel_delta > 0) ? (test->machine >= MAXSEQ) : (test->machine < 1)) {
176  break;
177  }
178 
179  test->machine += channel_delta;
180  }
181 
182  if (!SEQ_valid_strip_channel(test)) {
183  /* Blender 2.4x would remove the strip.
184  * nicer to move it to the end */
185 
186  Sequence *seq;
187  int new_frame = SEQ_time_right_handle_frame_get(evil_scene, test);
188 
189  for (seq = seqbasep->first; seq; seq = seq->next) {
190  if (seq->machine == orig_machine) {
191  new_frame = max_ii(new_frame, SEQ_time_right_handle_frame_get(evil_scene, seq));
192  }
193  }
194 
195  test->machine = orig_machine;
196  new_frame = new_frame + (test->start - SEQ_time_left_handle_frame_get(
197  evil_scene, test)); /* adjust by the startdisp */
198  SEQ_transform_translate_sequence(evil_scene, test, new_frame - test->start);
199  return false;
200  }
201 
202  return true;
203 }
204 
205 bool SEQ_transform_seqbase_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_scene)
206 {
207  return SEQ_transform_seqbase_shuffle_ex(seqbasep, test, evil_scene, 1);
208 }
209 
211  const Sequence *seq1,
212  const Sequence *seq2,
213  const int offset)
214 {
215  return (seq1 != seq2 && seq1->machine == seq2->machine &&
219  SEQ_time_right_handle_frame_get(scene, seq2))) == 0);
220 }
221 
223  SeqCollection *strips_to_shuffle,
224  ListBase *seqbasep,
225  char dir)
226 {
227  int offset = 0;
228  Sequence *seq;
229  bool all_conflicts_resolved = false;
230 
231  while (!all_conflicts_resolved) {
232  all_conflicts_resolved = true;
233  SEQ_ITERATOR_FOREACH (seq, strips_to_shuffle) {
234  LISTBASE_FOREACH (Sequence *, seq_other, seqbasep) {
235  if (!shuffle_seq_test_overlap(scene, seq, seq_other, offset)) {
236  continue;
237  }
238  if (SEQ_relation_is_effect_of_strip(seq_other, seq)) {
239  continue;
240  }
241  if (UNLIKELY(SEQ_collection_has_strip(seq_other, strips_to_shuffle))) {
242  CLOG_WARN(&LOG,
243  "Strip overlaps with itself or another strip, that is to be shuffled. "
244  "This should never happen.");
245  continue;
246  }
247 
248  all_conflicts_resolved = false;
249 
250  if (dir == 'L') {
251  offset = min_ii(offset,
254  }
255  else {
256  offset = max_ii(offset,
259  }
260  }
261  }
262  }
263 
264  return offset;
265 }
266 
268  SeqCollection *time_dependent_strips,
269  ListBase *seqbasep,
270  Scene *evil_scene,
271  ListBase *markers,
272  const bool use_sync_markers)
273 {
274  int offset_l = shuffle_seq_time_offset_get(evil_scene, strips_to_shuffle, seqbasep, 'L');
275  int offset_r = shuffle_seq_time_offset_get(evil_scene, strips_to_shuffle, seqbasep, 'R');
276  int offset = (-offset_l < offset_r) ? offset_l : offset_r;
277 
278  if (offset) {
279  Sequence *seq;
280  SEQ_ITERATOR_FOREACH (seq, strips_to_shuffle) {
281  SEQ_transform_translate_sequence(evil_scene, seq, offset);
282  seq->flag &= ~SEQ_OVERLAP;
283  }
284 
285  if (time_dependent_strips != NULL) {
286  SEQ_ITERATOR_FOREACH (seq, time_dependent_strips) {
287  SEQ_offset_animdata(evil_scene, seq, offset);
288  }
289  }
290 
291  if (use_sync_markers && !(evil_scene->toolsettings->lock_markers) && (markers != NULL)) {
292  TimeMarker *marker;
293  /* affect selected markers - it's unlikely that we will want to affect all in this way? */
294  for (marker = markers->first; marker; marker = marker->next) {
295  if (marker->flag & SELECT) {
296  marker->frame += offset;
297  }
298  }
299  }
300  }
301 
302  return offset ? false : true;
303 }
304 
306 {
307  SeqCollection *collection = SEQ_collection_create(__func__);
308  Sequence *seq;
309  SEQ_ITERATOR_FOREACH (seq, transformed_strips) {
310  if ((seq->type & SEQ_TYPE_EFFECT) == 0 || seq->seq1 == NULL) {
311  SEQ_collection_append_strip(seq, collection);
312  }
313  }
314  return collection;
315 }
316 
317 /* Query strips positioned after left edge of transformed strips bound-box. */
319  ListBase *seqbase,
320  SeqCollection *transformed_strips,
321  SeqCollection *time_dependent_strips)
322 {
323  int minframe = MAXFRAME;
324  {
325  Sequence *seq;
326  SEQ_ITERATOR_FOREACH (seq, transformed_strips) {
327  minframe = min_ii(minframe, SEQ_time_left_handle_frame_get(scene, seq));
328  }
329  }
330 
331  SeqCollection *collection = SEQ_collection_create(__func__);
332  LISTBASE_FOREACH (Sequence *, seq, seqbase) {
333  if (SEQ_collection_has_strip(seq, time_dependent_strips)) {
334  continue;
335  }
336  if (SEQ_collection_has_strip(seq, transformed_strips)) {
337  continue;
338  }
339 
340  if ((seq->flag & SELECT) == 0 && SEQ_time_left_handle_frame_get(scene, seq) >= minframe) {
341  SEQ_collection_append_strip(seq, collection);
342  }
343  }
344  return collection;
345 }
346 
347 /* Offset all strips positioned after left edge of transformed strips bound-box by amount equal
348  * to overlap of transformed strips. */
350  ListBase *seqbasep,
351  SeqCollection *transformed_strips,
352  SeqCollection *time_dependent_strips,
353  bool use_sync_markers)
354 {
356 
357  SeqCollection *right_side_strips = query_right_side_strips(
358  scene, seqbasep, transformed_strips, time_dependent_strips);
359 
360  /* Temporarily move right side strips beyond timeline boundary. */
361  Sequence *seq;
362  SEQ_ITERATOR_FOREACH (seq, right_side_strips) {
363  seq->machine += MAXSEQ * 2;
364  }
365 
366  /* Shuffle transformed standalone strips. This is because transformed strips can overlap with
367  * strips on left side. */
368  SeqCollection *standalone_strips = extract_standalone_strips(transformed_strips);
370  standalone_strips, time_dependent_strips, seqbasep, scene, markers, use_sync_markers);
371  SEQ_collection_free(standalone_strips);
372 
373  /* Move temporarily moved strips back to their original place and tag for shuffling. */
374  SEQ_ITERATOR_FOREACH (seq, right_side_strips) {
375  seq->machine -= MAXSEQ * 2;
376  }
377  /* Shuffle again to displace strips on right side. Final effect shuffling is done in
378  * SEQ_transform_handle_overlap. */
380  right_side_strips, NULL, seqbasep, scene, markers, use_sync_markers);
381  SEQ_collection_free(right_side_strips);
382 }
383 
385  ListBase *seqbasep,
386  SeqCollection *transformed_strips)
387 {
388  SeqCollection *collection = SEQ_query_unselected_strips(seqbasep);
389 
390  Sequence *seq, *seq_transformed;
391  SEQ_ITERATOR_FOREACH (seq, collection) {
392  bool does_overlap = false;
393 
394  SEQ_ITERATOR_FOREACH (seq_transformed, transformed_strips) {
395  /* Effects of transformed strips can be unselected. These must not be included. */
396  if (seq == seq_transformed) {
397  SEQ_collection_remove_strip(seq, collection);
398  }
399  if (SEQ_transform_test_overlap_seq_seq(scene, seq, seq_transformed)) {
400  does_overlap = true;
401  }
402  }
403 
404  if (!does_overlap) {
405  SEQ_collection_remove_strip(seq, collection);
406  }
407  }
408 
409  return collection;
410 }
411 
412 typedef enum eOvelapDescrition {
413  /* No overlap. */
415  /* Overlapping strip covers overlapped completely. */
417  /* Overlapping strip is inside overlapped. */
419  /* Partial overlap between 2 strips. */
423 
425  const Sequence *transformed,
426  const Sequence *target)
427 {
428  if (SEQ_time_left_handle_frame_get(scene, transformed) <=
430  SEQ_time_right_handle_frame_get(scene, transformed) >=
432  return STRIP_OVERLAP_IS_FULL;
433  }
434  if (SEQ_time_left_handle_frame_get(scene, transformed) >
436  SEQ_time_right_handle_frame_get(scene, transformed) <
439  }
440  if (SEQ_time_left_handle_frame_get(scene, transformed) <=
443  SEQ_time_right_handle_frame_get(scene, transformed)) {
445  }
446  if (SEQ_time_left_handle_frame_get(scene, transformed) <=
449  SEQ_time_right_handle_frame_get(scene, transformed)) {
451  }
452  return STRIP_OVERLAP_NONE;
453 }
454 
455 /* Split strip in 3 parts, remove middle part and fit transformed inside. */
457  ListBase *seqbasep,
458  const Sequence *transformed,
459  Sequence *target)
460 {
461  /* Because we are doing a soft split, bmain is not used in SEQ_edit_strip_split, so we can pass
462  * NULL here. */
463  Main *bmain = NULL;
464 
465  Sequence *split_strip = SEQ_edit_strip_split(bmain,
466  scene,
467  seqbasep,
468  target,
471  NULL);
472  SEQ_edit_strip_split(bmain,
473  scene,
474  seqbasep,
475  split_strip,
478  NULL);
479  SEQ_edit_flag_for_removal(scene, seqbasep, split_strip);
481 }
482 
483 /* Trim strips by adjusting handle position.
484  * This is bit more complicated in case overlap happens on effect. */
486  ListBase *seqbasep,
487  const Sequence *transformed,
488  Sequence *target,
489  const eOvelapDescrition overlap)
490 {
492  target, scene, seqbasep, SEQ_query_strip_effect_chain);
493 
494  /* Expand collection by adding all target's children, effects and their children. */
495  if ((target->type & SEQ_TYPE_EFFECT) != 0) {
497  }
498 
499  /* Trim all non effects, that have influence on effect length which is overlapping. */
500  Sequence *seq;
501  SEQ_ITERATOR_FOREACH (seq, targets) {
502  if ((seq->type & SEQ_TYPE_EFFECT) != 0 && SEQ_effect_get_num_inputs(seq->type) > 0) {
503  continue;
504  }
505  if (overlap == STRIP_OVERLAP_LEFT_SIDE) {
507  scene, seq, SEQ_time_right_handle_frame_get(scene, transformed));
508  }
509  else {
512  scene, seq, SEQ_time_left_handle_frame_get(scene, transformed));
513  }
514  }
515  SEQ_collection_free(targets);
516 }
517 
519  ListBase *seqbasep,
520  SeqCollection *transformed_strips)
521 {
522  SeqCollection *targets = query_overwrite_targets(scene, seqbasep, transformed_strips);
523  SeqCollection *strips_to_delete = SEQ_collection_create(__func__);
524 
525  Sequence *target;
526  Sequence *transformed;
527  SEQ_ITERATOR_FOREACH (target, targets) {
528  SEQ_ITERATOR_FOREACH (transformed, transformed_strips) {
529  if (transformed->machine != target->machine) {
530  continue;
531  }
532 
533  const eOvelapDescrition overlap = overlap_description_get(scene, transformed, target);
534 
535  if (overlap == STRIP_OVERLAP_IS_FULL) {
536  SEQ_collection_append_strip(target, strips_to_delete);
537  }
538  else if (overlap == STRIP_OVERLAP_IS_INSIDE) {
539  seq_transform_handle_overwrite_split(scene, seqbasep, transformed, target);
540  }
542  seq_transform_handle_overwrite_trim(scene, seqbasep, transformed, target, overlap);
543  }
544  }
545  }
546 
547  SEQ_collection_free(targets);
548 
549  /* Remove covered strips. This must be done in separate loop, because `SEQ_edit_strip_split()`
550  * also uses `SEQ_edit_remove_flagged_sequences()`. See T91096. */
551  if (SEQ_collection_len(strips_to_delete) > 0) {
552  Sequence *seq;
553  SEQ_ITERATOR_FOREACH (seq, strips_to_delete) {
554  SEQ_edit_flag_for_removal(scene, seqbasep, seq);
555  }
557  }
558  SEQ_collection_free(strips_to_delete);
559 }
560 
562  ListBase *seqbasep,
563  SeqCollection *transformed_strips,
564  SeqCollection *time_dependent_strips,
565  bool use_sync_markers)
566 {
568 
569  /* Shuffle non strips with no effects attached. */
570  SeqCollection *standalone_strips = extract_standalone_strips(transformed_strips);
572  standalone_strips, time_dependent_strips, seqbasep, scene, markers, use_sync_markers);
573  SEQ_collection_free(standalone_strips);
574 }
575 
577  ListBase *seqbasep,
578  SeqCollection *transformed_strips,
579  SeqCollection *time_dependent_strips,
580  bool use_sync_markers)
581 {
583 
584  switch (overlap_mode) {
585  case SEQ_OVERLAP_EXPAND:
587  scene, seqbasep, transformed_strips, time_dependent_strips, use_sync_markers);
588  break;
590  seq_transform_handle_overwrite(scene, seqbasep, transformed_strips);
591  break;
592  case SEQ_OVERLAP_SHUFFLE:
594  scene, seqbasep, transformed_strips, time_dependent_strips, use_sync_markers);
595  break;
596  }
597 
598  /* If any effects still overlap, we need to move them up.
599  * In some cases other strips can be overlapping still, see T90646. */
600  Sequence *seq;
601  SEQ_ITERATOR_FOREACH (seq, transformed_strips) {
602  if (SEQ_transform_test_overlap(scene, seqbasep, seq)) {
603  SEQ_transform_seqbase_shuffle(seqbasep, seq, scene);
604  }
605  seq->flag &= ~SEQ_OVERLAP;
606  }
607 }
608 
610  ListBase *seqbase,
611  const int delta,
612  const int timeline_frame)
613 {
614  LISTBASE_FOREACH (Sequence *, seq, seqbase) {
615  if (SEQ_time_left_handle_frame_get(scene, seq) >= timeline_frame) {
618  }
619  }
620 
622  LISTBASE_FOREACH (TimeMarker *, marker, &scene->markers) {
623  if (marker->frame >= timeline_frame) {
624  marker->frame += delta;
625  }
626  }
627  }
628 }
629 
631 {
633  return seq->flag & SEQ_LOCK ||
634  (SEQ_channel_is_locked(channel) && ((seq->flag & SEQ_IGNORE_CHANNEL_LOCK) == 0));
635 }
636 
637 void SEQ_image_transform_mirror_factor_get(const Sequence *seq, float r_mirror[2])
638 {
639  r_mirror[0] = 1.0f;
640  r_mirror[1] = 1.0f;
641 
642  if ((seq->flag & SEQ_FLIPX) != 0) {
643  r_mirror[0] = -1.0f;
644  }
645  if ((seq->flag & SEQ_FLIPY) != 0) {
646  r_mirror[1] = -1.0f;
647  }
648 }
649 
651  const Sequence *seq,
652  float r_origin[2])
653 {
654  float image_size[2];
655  StripElem *strip_elem = seq->strip->stripdata;
656  if (strip_elem == NULL) {
657  image_size[0] = scene->r.xsch;
658  image_size[1] = scene->r.ysch;
659  }
660  else {
661  image_size[0] = strip_elem->orig_width;
662  image_size[1] = strip_elem->orig_height;
663  }
664 
665  const StripTransform *transform = seq->strip->transform;
666  r_origin[0] = (image_size[0] * transform->origin[0]) - (image_size[0] * 0.5f) + transform->xofs;
667  r_origin[1] = (image_size[1] * transform->origin[1]) - (image_size[1] * 0.5f) + transform->yofs;
668 
669  const float viewport_pixel_aspect[2] = {scene->r.xasp / scene->r.yasp, 1.0f};
670  float mirror[2];
672  mul_v2_v2(r_origin, mirror);
673  mul_v2_v2(r_origin, viewport_pixel_aspect);
674 }
675 
677  const Sequence *seq,
678  bool apply_rotation,
679  float r_quad[4][2])
680 {
682  StripCrop *crop = seq->strip->crop;
683 
684  int image_size[2] = {scene->r.xsch, scene->r.ysch};
685  if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE)) {
686  image_size[0] = seq->strip->stripdata->orig_width;
687  image_size[1] = seq->strip->stripdata->orig_height;
688  }
689 
690  float transform_matrix[4][4];
691  float rotation_matrix[3][3];
692  axis_angle_to_mat3_single(rotation_matrix, 'Z', apply_rotation ? transform->rotation : 0.0f);
693  loc_rot_size_to_mat4(transform_matrix,
694  (const float[]){transform->xofs, transform->yofs, 0.0f},
695  rotation_matrix,
696  (const float[]){transform->scale_x, transform->scale_y, 1.0f});
697  const float origin[2] = {image_size[0] * transform->origin[0],
698  image_size[1] * transform->origin[1]};
699  const float pivot[3] = {origin[0] - (image_size[0] / 2), origin[1] - (image_size[1] / 2), 0.0f};
700  transform_pivot_set_m4(transform_matrix, pivot);
701 
702  float quad_temp[4][3];
703  for (int i = 0; i < 4; i++) {
704  zero_v2(quad_temp[i]);
705  }
706 
707  quad_temp[0][0] = (image_size[0] / 2) - crop->right;
708  quad_temp[0][1] = (image_size[1] / 2) - crop->top;
709  quad_temp[1][0] = (image_size[0] / 2) - crop->right;
710  quad_temp[1][1] = (-image_size[1] / 2) + crop->bottom;
711  quad_temp[2][0] = (-image_size[0] / 2) + crop->left;
712  quad_temp[2][1] = (-image_size[1] / 2) + crop->bottom;
713  quad_temp[3][0] = (-image_size[0] / 2) + crop->left;
714  quad_temp[3][1] = (image_size[1] / 2) - crop->top;
715 
716  float mirror[2];
718 
719  const float viewport_pixel_aspect[2] = {scene->r.xasp / scene->r.yasp, 1.0f};
720 
721  for (int i = 0; i < 4; i++) {
722  mul_m4_v3(transform_matrix, quad_temp[i]);
723  mul_v2_v2(quad_temp[i], mirror);
724  mul_v2_v2(quad_temp[i], viewport_pixel_aspect);
725  copy_v2_v2(r_quad[i], quad_temp[i]);
726  }
727 }
728 
730  const Sequence *seq,
731  bool apply_rotation,
732  float r_quad[4][2])
733 {
734  seq_image_transform_quad_get_ex(scene, seq, apply_rotation, r_quad);
735 }
736 
738  const Sequence *seq,
739  float r_quad[4][2])
740 {
741  seq_image_transform_quad_get_ex(scene, seq, true, r_quad);
742 }
743 
744 void SEQ_image_preview_unit_to_px(const Scene *scene, const float co_src[2], float co_dst[2])
745 {
746  co_dst[0] = co_src[0] * scene->r.xsch;
747  co_dst[1] = co_src[1] * scene->r.ysch;
748 }
749 
750 void SEQ_image_preview_unit_from_px(const Scene *scene, const float co_src[2], float co_dst[2])
751 {
752  co_dst[0] = co_src[0] / scene->r.xsch;
753  co_dst[1] = co_src[1] / scene->r.ysch;
754 }
755 
757  Scene *scene, SeqCollection *strips, bool apply_rotation, float r_min[2], float r_max[2])
758 {
759  Sequence *seq;
760 
761  INIT_MINMAX2(r_min, r_max);
762  SEQ_ITERATOR_FOREACH (seq, strips) {
763  float quad[4][2];
764  SEQ_image_transform_quad_get(scene, seq, apply_rotation, quad);
765  for (int i = 0; i < 4; i++) {
766  minmax_v2v2_v2(r_min, r_max, quad[i]);
767  }
768  }
769 }
#define BLI_assert(a)
Definition: BLI_assert.h:46
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
void loc_rot_size_to_mat4(float R[4][4], const float loc[3], const float rot[3][3], const float size[3])
Definition: math_matrix.c:2537
void transform_pivot_set_m4(float mat[4][4], const float pivot[3])
Definition: math_matrix.c:2369
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:729
void axis_angle_to_mat3_single(float R[3][3], char axis, float angle)
MINLINE void mul_v2_v2(float r[2], const float a[2])
MINLINE void copy_v2_v2(float r[2], const float a[2])
void minmax_v2v2_v2(float min[2], float max[2], const float vec[2])
Definition: math_vector.c:890
MINLINE void zero_v2(float r[2])
#define INIT_MINMAX2(min, max)
#define UNLIKELY(x)
#define ELEM(...)
#define CLOG_WARN(clg_ref,...)
Definition: CLG_log.h:189
eSeqOverlapMode
@ SEQ_OVERLAP_EXPAND
@ SEQ_OVERLAP_SHUFFLE
@ SEQ_OVERLAP_OVERWRITE
#define MAXFRAME
@ SEQ_TYPE_META
@ SEQ_TYPE_IMAGE
@ SEQ_TYPE_EFFECT
@ SEQ_TYPE_MOVIE
@ SEQ_FLIPX
@ SEQ_IGNORE_CHANNEL_LOCK
@ SEQ_OVERLAP
@ SEQ_FLIPY
@ SEQ_LOCK
#define MAXSEQ
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
@ SEQ_SPLIT_SOFT
Definition: SEQ_edit.h:61
#define SEQ_ITERATOR_FOREACH(var, collection)
Definition: SEQ_iterator.h:35
void SEQ_offset_animdata(Scene *scene, Sequence *seq, int ofs)
Definition: animation.c:67
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
SeqTimelineChannel * SEQ_channel_get_by_index(const ListBase *channels, const int channel_index)
Definition: channels.c:59
bool SEQ_channel_is_locked(const SeqTimelineChannel *channel)
Definition: channels.c:75
#define SELECT
Scene scene
int SEQ_effect_get_num_inputs(int seq_type)
Definition: effects.c:3741
GPUBatch * quad
const vector< Marker > & markers
SeqCollection * SEQ_query_by_reference(Sequence *seq_reference, const Scene *scene, ListBase *seqbase, void seq_query_func(const Scene *scene, Sequence *seq_reference, ListBase *seqbase, SeqCollection *collection))
Definition: iterator.c:105
uint SEQ_collection_len(const SeqCollection *collection)
Definition: iterator.c:95
void SEQ_query_strip_effect_chain(const Scene *scene, Sequence *seq_reference, ListBase *seqbase, SeqCollection *collection)
Definition: iterator.c:335
void SEQ_collection_expand(const Scene *scene, ListBase *seqbase, SeqCollection *collection, void seq_query_func(const Scene *scene, Sequence *seq_reference, ListBase *seqbase, SeqCollection *collection))
Definition: iterator.c:151
bool SEQ_collection_remove_strip(Sequence *seq, SeqCollection *collection)
Definition: iterator.c:128
SeqCollection * SEQ_collection_create(const char *name)
Definition: iterator.c:87
bool SEQ_collection_append_strip(Sequence *seq, SeqCollection *collection)
Definition: iterator.c:117
SeqCollection * SEQ_query_unselected_strips(ListBase *seqbase)
Definition: iterator.c:323
bool SEQ_collection_has_strip(const Sequence *seq, const SeqCollection *collection)
Definition: iterator.c:100
void SEQ_collection_free(SeqCollection *collection)
Definition: iterator.c:81
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
static int left
SeqCollection * seq_sequence_lookup_effects_by_seq(const Scene *scene, const Sequence *key)
Sequence * seq_sequence_lookup_meta_by_seq(const Scene *scene, const Sequence *key)
eSeqOverlapMode SEQ_tool_settings_overlap_mode_get(Scene *scene)
Definition: sequencer.c:376
bool SEQ_valid_strip_channel(Sequence *seq)
Definition: sequencer.c:653
void SEQ_edit_flag_for_removal(Scene *scene, ListBase *seqbase, Sequence *seq)
Definition: strip_edit.c:163
Sequence * SEQ_edit_strip_split(Main *bmain, Scene *scene, ListBase *seqbase, Sequence *seq, const int timeline_frame, const eSeqSplitMethod method, const char **r_error)
Definition: strip_edit.c:409
void SEQ_edit_remove_flagged_sequences(Scene *scene, ListBase *seqbase)
Definition: strip_edit.c:180
bool SEQ_relation_is_effect_of_strip(const Sequence *effect, const Sequence *input)
void SEQ_relations_invalidate_cache_preprocessed(Scene *scene, Sequence *seq)
void SEQ_time_right_handle_frame_set(const Scene *scene, Sequence *seq, int val)
Definition: strip_time.c:539
void SEQ_time_update_meta_strip_range(const Scene *scene, Sequence *seq_meta)
Definition: strip_time.c:147
void seq_time_update_effects_strip_range(const Scene *scene, SeqCollection *effects)
Definition: strip_time.c:216
void seq_time_translate_handles(const Scene *scene, Sequence *seq, const int offset)
Definition: strip_time.c:555
int SEQ_time_left_handle_frame_get(const Scene *UNUSED(scene), const Sequence *seq)
Definition: strip_time.c:506
void SEQ_time_left_handle_frame_set(const Scene *scene, Sequence *seq, int val)
Definition: strip_time.c:524
int SEQ_time_right_handle_frame_get(const Scene *scene, const Sequence *seq)
Definition: strip_time.c:515
void SEQ_image_transform_quad_get(const Scene *scene, const Sequence *seq, bool apply_rotation, float r_quad[4][2])
bool SEQ_transform_seqbase_isolated_sel_check(ListBase *seqbase)
static int shuffle_seq_time_offset_get(const Scene *scene, SeqCollection *strips_to_shuffle, ListBase *seqbasep, char dir)
bool SEQ_transform_seqbase_shuffle_ex(ListBase *seqbasep, Sequence *test, Scene *evil_scene, int channel_delta)
static void seq_image_transform_quad_get_ex(const Scene *scene, const Sequence *seq, bool apply_rotation, float r_quad[4][2])
static SeqCollection * extract_standalone_strips(SeqCollection *transformed_strips)
bool SEQ_transform_seqbase_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_scene)
static void seq_transform_handle_overlap_shuffle(Scene *scene, ListBase *seqbasep, SeqCollection *transformed_strips, SeqCollection *time_dependent_strips, bool use_sync_markers)
bool SEQ_transform_is_locked(ListBase *channels, Sequence *seq)
static eOvelapDescrition overlap_description_get(const Scene *scene, const Sequence *transformed, const Sequence *target)
void SEQ_image_preview_unit_to_px(const Scene *scene, const float co_src[2], float co_dst[2])
static void seq_transform_handle_expand_to_fit(Scene *scene, ListBase *seqbasep, SeqCollection *transformed_strips, SeqCollection *time_dependent_strips, bool use_sync_markers)
static void seq_transform_handle_overwrite(Scene *scene, ListBase *seqbasep, SeqCollection *transformed_strips)
bool SEQ_transform_test_overlap(const Scene *scene, ListBase *seqbasep, Sequence *test)
static void seq_transform_handle_overwrite_split(Scene *scene, ListBase *seqbasep, const Sequence *transformed, Sequence *target)
static SeqCollection * query_overwrite_targets(const Scene *scene, ListBase *seqbasep, SeqCollection *transformed_strips)
void SEQ_transform_fix_single_image_seq_offsets(const Scene *scene, Sequence *seq)
void SEQ_transform_handle_overlap(Scene *scene, ListBase *seqbasep, SeqCollection *transformed_strips, SeqCollection *time_dependent_strips, bool use_sync_markers)
void SEQ_image_transform_origin_offset_pixelspace_get(const Scene *scene, const Sequence *seq, float r_origin[2])
void SEQ_image_transform_final_quad_get(const Scene *scene, const Sequence *seq, float r_quad[4][2])
bool SEQ_transform_sequence_can_be_translated(Sequence *seq)
static SeqCollection * query_right_side_strips(const Scene *scene, ListBase *seqbase, SeqCollection *transformed_strips, SeqCollection *time_dependent_strips)
bool SEQ_transform_seqbase_shuffle_time(SeqCollection *strips_to_shuffle, SeqCollection *time_dependent_strips, ListBase *seqbasep, Scene *evil_scene, ListBase *markers, const bool use_sync_markers)
static bool shuffle_seq_test_overlap(const Scene *scene, const Sequence *seq1, const Sequence *seq2, const int offset)
void SEQ_transform_translate_sequence(Scene *evil_scene, Sequence *seq, int delta)
bool SEQ_transform_single_image_check(Sequence *seq)
void SEQ_image_transform_mirror_factor_get(const Sequence *seq, float r_mirror[2])
void SEQ_image_transform_bounding_box_from_collection(Scene *scene, SeqCollection *strips, bool apply_rotation, float r_min[2], float r_max[2])
static CLG_LogRef LOG
eOvelapDescrition
@ STRIP_OVERLAP_RIGHT_SIDE
@ STRIP_OVERLAP_LEFT_SIDE
@ STRIP_OVERLAP_IS_INSIDE
@ STRIP_OVERLAP_IS_FULL
@ STRIP_OVERLAP_NONE
void SEQ_image_preview_unit_from_px(const Scene *scene, const float co_src[2], float co_dst[2])
static void seq_transform_handle_overwrite_trim(Scene *scene, ListBase *seqbasep, const Sequence *transformed, Sequence *target, const eOvelapDescrition overlap)
bool SEQ_transform_test_overlap_seq_seq(const Scene *scene, Sequence *seq1, Sequence *seq2)
void SEQ_transform_offset_after_frame(Scene *scene, ListBase *seqbase, const int delta, const int timeline_frame)
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
struct ToolSettings * toolsettings
struct RenderData r
ListBase markers
struct Sequence * seq3
ListBase seqbase
struct Sequence * seq1
struct Sequence * seq2
struct Sequence * next
StripTransform * transform
StripElem * stripdata
StripCrop * crop
unsigned int flag
struct TimeMarker * next