Blender V4.5
strip_transform.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 * SPDX-FileCopyrightText: 2003-2009 Blender Authors
3 * SPDX-FileCopyrightText: 2005-2006 Peter Schlaile <peter [at] schlaile [dot] de>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later */
6
10
11#include "BLI_bounds.hh"
12#include "BLI_math_base.hh"
13#include "DNA_scene_types.h"
14#include "DNA_sequence_types.h"
15
16#include "BLI_listbase.h"
17#include "BLI_math_base.h"
18#include "BLI_math_matrix.hh"
20
21#include "SEQ_animation.hh"
22#include "SEQ_channels.hh"
23#include "SEQ_edit.hh"
24#include "SEQ_effects.hh"
25#include "SEQ_iterator.hh"
26#include "SEQ_relations.hh"
27#include "SEQ_sequencer.hh"
28#include "SEQ_time.hh"
29#include "SEQ_transform.hh"
30
31#include "sequencer.hh"
32#include "strip_time.hh"
33
34namespace blender::seq {
35
37{
38 return (strip->flag & SEQ_SINGLE_FRAME_CONTENT) != 0;
39}
40
42{
43 return !(strip->type & STRIP_TYPE_EFFECT) || (effect_get_num_inputs(strip->type) == 0);
44}
45
46bool transform_test_overlap(const Scene *scene, Strip *strip1, Strip *strip2)
47{
48 return (
49 strip1 != strip2 && strip1->channel == strip2->channel &&
50 ((time_right_handle_frame_get(scene, strip1) <= time_left_handle_frame_get(scene, strip2)) ||
51 (time_left_handle_frame_get(scene, strip1) >=
52 time_right_handle_frame_get(scene, strip2))) == 0);
53}
54
55bool transform_test_overlap(const Scene *scene, ListBase *seqbasep, Strip *test)
56{
57 Strip *strip;
58
59 strip = static_cast<Strip *>(seqbasep->first);
60 while (strip) {
61 if (transform_test_overlap(scene, test, strip)) {
62 return true;
63 }
64
65 strip = strip->next;
66 }
67 return false;
68}
69
70void transform_translate_strip(Scene *evil_scene, Strip *strip, int delta)
71{
72 if (delta == 0) {
73 return;
74 }
75
76 /* Meta strips requires their content is to be translated, and then frame range of the meta is
77 * updated based on nested strips. This won't work for empty meta-strips,
78 * so they can be treated as normal strip. */
79 if (strip->type == STRIP_TYPE_META && !BLI_listbase_is_empty(&strip->seqbase)) {
80 LISTBASE_FOREACH (Strip *, strip_child, &strip->seqbase) {
81 transform_translate_strip(evil_scene, strip_child, delta);
82 }
83 /* Move meta start/end points. */
84 strip_time_translate_handles(evil_scene, strip, delta);
85 }
86 else if (strip->input1 == nullptr && strip->input2 == nullptr) { /* All other strip types. */
87 strip->start += delta;
88 /* Only to make files usable in older versions. */
89 strip->startdisp = time_left_handle_frame_get(evil_scene, strip);
90 strip->enddisp = time_right_handle_frame_get(evil_scene, strip);
91 }
92
93 offset_animdata(evil_scene, strip, delta);
94 blender::Span<Strip *> effects = SEQ_lookup_effects_by_strip(evil_scene->ed, strip);
95 strip_time_update_effects_strip_range(evil_scene, effects);
96 time_update_meta_strip_range(evil_scene, lookup_meta_by_strip(evil_scene->ed, strip));
97}
98
100 Strip *test,
101 Scene *evil_scene,
102 int channel_delta)
103{
104 const int orig_channel = test->channel;
105 BLI_assert(ELEM(channel_delta, -1, 1));
106
107 strip_channel_set(test, test->channel + channel_delta);
108
109 const ListBase *channels = channels_displayed_get(editing_get(evil_scene));
110 SeqTimelineChannel *channel = channel_get_by_index(channels, test->channel);
111
112 while (transform_test_overlap(evil_scene, seqbasep, test) || channel_is_muted(channel) ||
113 channel_is_locked(channel))
114 {
115 if ((channel_delta > 0) ? (test->channel >= MAX_CHANNELS) : (test->channel < 1)) {
116 break;
117 }
118
119 strip_channel_set(test, test->channel + channel_delta);
120 channel = channel_get_by_index(channels, test->channel);
121 }
122
123 if (!is_valid_strip_channel(test)) {
124 /* Blender 2.4x would remove the strip.
125 * nicer to move it to the end */
126
127 int new_frame = time_right_handle_frame_get(evil_scene, test);
128
129 LISTBASE_FOREACH (Strip *, strip, seqbasep) {
130 if (strip->channel == orig_channel) {
131 new_frame = max_ii(new_frame, time_right_handle_frame_get(evil_scene, strip));
132 }
133 }
134
135 strip_channel_set(test, orig_channel);
136
137 new_frame = new_frame + (test->start - time_left_handle_frame_get(
138 evil_scene, test)); /* adjust by the startdisp */
139 transform_translate_strip(evil_scene, test, new_frame - test->start);
140 return false;
141 }
142
143 return true;
144}
145
146bool transform_seqbase_shuffle(ListBase *seqbasep, Strip *test, Scene *evil_scene)
147{
148 return transform_seqbase_shuffle_ex(seqbasep, test, evil_scene, 1);
149}
150
151static bool shuffle_strip_test_overlap(const Scene *scene,
152 const Strip *strip1,
153 const Strip *strip2,
154 const int offset)
155{
156 BLI_assert(strip1 != strip2);
157 return (strip1->channel == strip2->channel &&
158 ((time_right_handle_frame_get(scene, strip1) + offset <=
159 time_left_handle_frame_get(scene, strip2)) ||
160 (time_left_handle_frame_get(scene, strip1) + offset >=
161 time_right_handle_frame_get(scene, strip2))) == 0);
162}
163
164static int shuffle_strip_time_offset_get(const Scene *scene,
165 blender::Span<Strip *> strips_to_shuffle,
166 ListBase *seqbasep,
167 char dir)
168{
169 int offset = 0;
170 bool all_conflicts_resolved = false;
171
172 while (!all_conflicts_resolved) {
173 all_conflicts_resolved = true;
174 for (Strip *strip : strips_to_shuffle) {
175 LISTBASE_FOREACH (Strip *, strip_other, seqbasep) {
176 if (strips_to_shuffle.contains(strip_other)) {
177 continue;
178 }
179 if (relation_is_effect_of_strip(strip_other, strip)) {
180 continue;
181 }
182 if (!shuffle_strip_test_overlap(scene, strip, strip_other, offset)) {
183 continue;
184 }
185
186 all_conflicts_resolved = false;
187
188 if (dir == 'L') {
189 offset = min_ii(offset,
190 time_left_handle_frame_get(scene, strip_other) -
191 time_right_handle_frame_get(scene, strip));
192 }
193 else {
194 offset = max_ii(offset,
195 time_right_handle_frame_get(scene, strip_other) -
196 time_left_handle_frame_get(scene, strip));
197 }
198 }
199 }
200 }
201
202 return offset;
203}
204
206 ListBase *seqbasep,
207 Scene *evil_scene,
208 ListBase *markers,
209 const bool use_sync_markers)
210{
213 strips_to_shuffle, empty_set, seqbasep, evil_scene, markers, use_sync_markers);
214}
215
217 blender::Span<Strip *> time_dependent_strips,
218 ListBase *seqbasep,
219 Scene *evil_scene,
220 ListBase *markers,
221 const bool use_sync_markers)
222{
223 int offset_l = shuffle_strip_time_offset_get(evil_scene, strips_to_shuffle, seqbasep, 'L');
224 int offset_r = shuffle_strip_time_offset_get(evil_scene, strips_to_shuffle, seqbasep, 'R');
225 int offset = (-offset_l < offset_r) ? offset_l : offset_r;
226
227 if (offset) {
228 for (Strip *strip : strips_to_shuffle) {
229 transform_translate_strip(evil_scene, strip, offset);
230 strip->flag &= ~SEQ_OVERLAP;
231 }
232
233 if (!time_dependent_strips.is_empty()) {
234 for (Strip *strip : time_dependent_strips) {
235 offset_animdata(evil_scene, strip, offset);
236 }
237 }
238
239 if (use_sync_markers && !(evil_scene->toolsettings->lock_markers) && (markers != nullptr)) {
240 /* affect selected markers - it's unlikely that we will want to affect all in this way? */
241 LISTBASE_FOREACH (TimeMarker *, marker, markers) {
242 if (marker->flag & SELECT) {
243 marker->frame += offset;
244 }
245 }
246 }
247 }
248
249 return offset ? false : true;
250}
251
253 blender::Span<Strip *> transformed_strips)
254{
255 blender::VectorSet<Strip *> standalone_strips;
256
257 for (Strip *strip : transformed_strips) {
258 if ((strip->type & STRIP_TYPE_EFFECT) == 0 || strip->input1 == nullptr) {
259 standalone_strips.add(strip);
260 }
261 }
262 return standalone_strips;
263}
264
265/* Query strips positioned after left edge of transformed strips bound-box. */
267 const Scene *scene,
268 ListBase *seqbase,
269 blender::Span<Strip *> transformed_strips,
270 blender::Span<Strip *> time_dependent_strips)
271{
272 int minframe = MAXFRAME;
273 {
274 for (Strip *strip : transformed_strips) {
275 minframe = min_ii(minframe, time_left_handle_frame_get(scene, strip));
276 }
277 }
278
279 blender::VectorSet<Strip *> right_side_strips;
280 LISTBASE_FOREACH (Strip *, strip, seqbase) {
281 if (!time_dependent_strips.is_empty() && time_dependent_strips.contains(strip)) {
282 continue;
283 }
284 if (transformed_strips.contains(strip)) {
285 continue;
286 }
287
288 if ((strip->flag & SELECT) == 0 && time_left_handle_frame_get(scene, strip) >= minframe) {
289 right_side_strips.add(strip);
290 }
291 }
292 return right_side_strips;
293}
294
295/* Offset all strips positioned after left edge of transformed strips bound-box by amount equal
296 * to overlap of transformed strips. */
298 ListBase *seqbasep,
299 blender::Span<Strip *> transformed_strips,
300 blender::Span<Strip *> time_dependent_strips,
301 bool use_sync_markers)
302{
303 ListBase *markers = &scene->markers;
304
306 scene, seqbasep, transformed_strips, time_dependent_strips);
307
308 /* Temporarily move right side strips beyond timeline boundary. */
309 for (Strip *strip : right_side_strips) {
310 strip->channel += MAX_CHANNELS * 2;
311 }
312
313 /* Shuffle transformed standalone strips. This is because transformed strips can overlap with
314 * strips on left side. */
315 blender::VectorSet standalone_strips = extract_standalone_strips(transformed_strips);
317 standalone_strips, time_dependent_strips, seqbasep, scene, markers, use_sync_markers);
318
319 /* Move temporarily moved strips back to their original place and tag for shuffling. */
320 for (Strip *strip : right_side_strips) {
321 strip->channel -= MAX_CHANNELS * 2;
322 }
323 /* Shuffle again to displace strips on right side. Final effect shuffling is done in
324 * SEQ_transform_handle_overlap. */
325 transform_seqbase_shuffle_time(right_side_strips, seqbasep, scene, markers, use_sync_markers);
326}
327
329 const Scene *scene, ListBase *seqbasep, blender::Span<Strip *> transformed_strips)
330{
331 blender::VectorSet<Strip *> overwrite_targets = query_unselected_strips(seqbasep);
332
333 /* Effects of transformed strips can be unselected. These must not be included. */
334 overwrite_targets.remove_if([&](Strip *strip) { return transformed_strips.contains(strip); });
335 overwrite_targets.remove_if([&](Strip *strip) {
336 bool does_overlap = false;
337 for (Strip *strip_transformed : transformed_strips) {
338 if (transform_test_overlap(scene, strip, strip_transformed)) {
339 does_overlap = true;
340 }
341 }
342
343 return !does_overlap;
344 });
345
346 return overwrite_targets;
347}
348
350 /* No overlap. */
352 /* Overlapping strip covers overlapped completely. */
354 /* Overlapping strip is inside overlapped. */
356 /* Partial overlap between 2 strips. */
359};
360
362 const Strip *transformed,
363 const Strip *target)
364{
365 if (time_left_handle_frame_get(scene, transformed) <=
366 time_left_handle_frame_get(scene, target) &&
367 time_right_handle_frame_get(scene, transformed) >=
368 time_right_handle_frame_get(scene, target))
369 {
371 }
372 if (time_left_handle_frame_get(scene, transformed) > time_left_handle_frame_get(scene, target) &&
373 time_right_handle_frame_get(scene, transformed) < time_right_handle_frame_get(scene, target))
374 {
376 }
377 if (time_left_handle_frame_get(scene, transformed) <=
378 time_left_handle_frame_get(scene, target) &&
379 time_left_handle_frame_get(scene, target) <= time_right_handle_frame_get(scene, transformed))
380 {
382 }
383 if (time_left_handle_frame_get(scene, transformed) <=
384 time_right_handle_frame_get(scene, target) &&
385 time_right_handle_frame_get(scene, target) <=
386 time_right_handle_frame_get(scene, transformed))
387 {
389 }
390 return STRIP_OVERLAP_NONE;
391}
392
393/* Split strip in 3 parts, remove middle part and fit transformed inside. */
395 ListBase *seqbasep,
396 const Strip *transformed,
397 Strip *target)
398{
399 /* Because we are doing a soft split, bmain is not used in SEQ_edit_strip_split, so we can
400 * pass nullptr here. */
401 Main *bmain = nullptr;
402
403 Strip *split_strip = edit_strip_split(bmain,
404 scene,
405 seqbasep,
406 target,
407 time_left_handle_frame_get(scene, transformed),
409 true,
410 nullptr);
411 edit_strip_split(bmain,
412 scene,
413 seqbasep,
414 split_strip,
415 time_right_handle_frame_get(scene, transformed),
417 true,
418 nullptr);
419 edit_flag_for_removal(scene, seqbasep, split_strip);
420 edit_remove_flagged_strips(scene, seqbasep);
421}
422
423/* Trim strips by adjusting handle position.
424 * This is bit more complicated in case overlap happens on effect. */
426 ListBase *seqbasep,
427 const Strip *transformed,
428 Strip *target,
429 const eOvelapDescrition overlap)
430{
432 target, scene, seqbasep, query_strip_effect_chain);
433
434 /* Expand collection by adding all target's children, effects and their children. */
435 if ((target->type & STRIP_TYPE_EFFECT) != 0) {
436 iterator_set_expand(scene, seqbasep, targets, query_strip_effect_chain);
437 }
438
439 /* Trim all non effects, that have influence on effect length which is overlapping. */
440 for (Strip *strip : targets) {
441 if ((strip->type & STRIP_TYPE_EFFECT) != 0 && effect_get_num_inputs(strip->type) > 0) {
442 continue;
443 }
444 if (overlap == STRIP_OVERLAP_LEFT_SIDE) {
445 time_left_handle_frame_set(scene, strip, time_right_handle_frame_get(scene, transformed));
446 }
447 else {
449 time_right_handle_frame_set(scene, strip, time_left_handle_frame_get(scene, transformed));
450 }
451 }
452}
453
455 ListBase *seqbasep,
456 blender::Span<Strip *> transformed_strips)
457{
458 blender::VectorSet targets = query_overwrite_targets(scene, seqbasep, transformed_strips);
459 blender::VectorSet<Strip *> strips_to_delete;
460
461 for (Strip *target : targets) {
462 for (Strip *transformed : transformed_strips) {
463 if (transformed->channel != target->channel) {
464 continue;
465 }
466
467 const eOvelapDescrition overlap = overlap_description_get(scene, transformed, target);
468
469 if (overlap == STRIP_OVERLAP_IS_FULL) {
470 strips_to_delete.add(target);
471 }
472 else if (overlap == STRIP_OVERLAP_IS_INSIDE) {
473 strip_transform_handle_overwrite_split(scene, seqbasep, transformed, target);
474 }
476 strip_transform_handle_overwrite_trim(scene, seqbasep, transformed, target, overlap);
477 }
478 }
479 }
480
481 /* Remove covered strips. This must be done in separate loop, because
482 * `SEQ_edit_strip_split()` also uses `SEQ_edit_remove_flagged_sequences()`. See #91096. */
483 if (!strips_to_delete.is_empty()) {
484 for (Strip *strip : strips_to_delete) {
485 edit_flag_for_removal(scene, seqbasep, strip);
486 }
487 edit_remove_flagged_strips(scene, seqbasep);
488 }
489}
490
492 ListBase *seqbasep,
493 blender::Span<Strip *> transformed_strips,
494 blender::Span<Strip *> time_dependent_strips,
495 bool use_sync_markers)
496{
497 ListBase *markers = &scene->markers;
498
499 /* Shuffle non strips with no effects attached. */
500 blender::VectorSet standalone_strips = extract_standalone_strips(transformed_strips);
502 standalone_strips, time_dependent_strips, seqbasep, scene, markers, use_sync_markers);
503}
504
506 ListBase *seqbasep,
507 blender::Span<Strip *> transformed_strips,
508 bool use_sync_markers)
509{
511 transform_handle_overlap(scene, seqbasep, transformed_strips, empty_set, use_sync_markers);
512}
513
515 ListBase *seqbasep,
516 blender::Span<Strip *> transformed_strips,
517 blender::Span<Strip *> time_dependent_strips,
518 bool use_sync_markers)
519{
520 const eSeqOverlapMode overlap_mode = tool_settings_overlap_mode_get(scene);
521
522 switch (overlap_mode) {
525 scene, seqbasep, transformed_strips, time_dependent_strips, use_sync_markers);
526 break;
528 strip_transform_handle_overwrite(scene, seqbasep, transformed_strips);
529 break;
532 scene, seqbasep, transformed_strips, time_dependent_strips, use_sync_markers);
533 break;
534 }
535
536 /* If any effects still overlap, we need to move them up.
537 * In some cases other strips can be overlapping still, see #90646. */
538 for (Strip *strip : transformed_strips) {
539 if (transform_test_overlap(scene, seqbasep, strip)) {
540 transform_seqbase_shuffle(seqbasep, strip, scene);
541 }
542 strip->flag &= ~SEQ_OVERLAP;
543 }
544}
545
547 ListBase *seqbase,
548 const int delta,
549 const int timeline_frame)
550{
551 LISTBASE_FOREACH (Strip *, strip, seqbase) {
552 if (time_left_handle_frame_get(scene, strip) >= timeline_frame) {
553 transform_translate_strip(scene, strip, delta);
554 relations_invalidate_cache(scene, strip);
555 }
556 }
557
558 if (!scene->toolsettings->lock_markers) {
559 LISTBASE_FOREACH (TimeMarker *, marker, &scene->markers) {
560 if (marker->frame >= timeline_frame) {
561 marker->frame += delta;
562 }
563 }
564 }
565}
566
567void strip_channel_set(Strip *strip, int channel)
568{
569 strip->channel = math::clamp(channel, 1, MAX_CHANNELS);
570}
571
572bool transform_is_locked(ListBase *channels, const Strip *strip)
573{
574 const SeqTimelineChannel *channel = channel_get_by_index(channels, strip->channel);
575 return strip->flag & SEQ_LOCK ||
576 (channel_is_locked(channel) && ((strip->flag & SEQ_IGNORE_CHANNEL_LOCK) == 0));
577}
578
580{
581 float2 mirror(1.0f, 1.0f);
582
583 if ((strip->flag & SEQ_FLIPX) != 0) {
584 mirror.x = -1.0f;
585 }
586 if ((strip->flag & SEQ_FLIPY) != 0) {
587 mirror.y = -1.0f;
588 }
589 return mirror;
590}
591
592static float2 strip_raw_image_size_get(const Scene *scene, const Strip *strip)
593{
595 const StripElem *selem = strip->data->stripdata;
596 return {float(selem->orig_width), float(selem->orig_height)};
597 }
598
599 if (strip->type == STRIP_TYPE_MOVIECLIP) {
600 const MovieClip *clip = strip->clip;
601 if (clip != nullptr && clip->lastsize[0] != 0 && clip->lastsize[1] != 0) {
602 return {float(clip->lastsize[0]), float(clip->lastsize[1])};
603 }
604 }
605
606 return {float(scene->r.xsch), float(scene->r.ysch)};
607}
608
610{
611 const float2 image_size = strip_raw_image_size_get(scene, strip);
612 const StripTransform *transform = strip->data->transform;
613
614 const float2 origin(
615 (image_size[0] * transform->origin[0]) - (image_size[0] * 0.5f) + transform->xofs,
616 (image_size[1] * transform->origin[1]) - (image_size[1] * 0.5f) + transform->yofs);
617
618 const float2 viewport_pixel_aspect(scene->r.xasp / scene->r.yasp, 1.0f);
619 const float2 mirror = image_transform_mirror_factor_get(strip);
620
621 return origin * mirror * viewport_pixel_aspect;
622}
623
625 const Strip *strip,
626 bool apply_rotation = true)
627{
628 const StripTransform *transform = strip->data->transform;
629 const float2 image_size = strip_raw_image_size_get(scene, strip);
630 const float2 origin(image_size.x * transform->origin[0], image_size[1] * transform->origin[1]);
631 const float2 translation(transform->xofs, transform->yofs);
632 const float rotation = apply_rotation ? transform->rotation : 0.0f;
633 const float2 scale(transform->scale_x, transform->scale_y);
634 const float2 pivot = origin - (image_size / 2);
635
636 const float3x3 matrix = math::from_loc_rot_scale<float3x3>(translation, rotation, scale);
637 return math::from_origin_transform(matrix, pivot);
638}
639
641{
642 return seq_image_transform_matrix_get_ex(scene, strip);
643}
644
646 const Strip *strip,
647 bool apply_rotation)
648{
649 const float2 image_size = strip_raw_image_size_get(scene, strip);
650
651 const StripCrop *crop = strip->data->crop;
652 float2 quad[4]{
653 {(image_size[0] / 2) - crop->right, (image_size[1] / 2) - crop->top},
654 {(image_size[0] / 2) - crop->right, (-image_size[1] / 2) + crop->bottom},
655 {(-image_size[0] / 2) + crop->left, (-image_size[1] / 2) + crop->bottom},
656 {(-image_size[0] / 2) + crop->left, (image_size[1] / 2) - crop->top},
657 };
658
659 const float3x3 matrix = seq_image_transform_matrix_get_ex(scene, strip, apply_rotation);
660 const float2 viewport_pixel_aspect(scene->r.xasp / scene->r.yasp, 1.0f);
661 const float2 mirror = image_transform_mirror_factor_get(strip);
662
663 Array<float2> quad_transformed;
664 quad_transformed.reinitialize(4);
665
666 for (int i = 0; i < 4; i++) {
667 const float2 point = math::transform_point(matrix, quad[i]);
668 quad_transformed[i] = point * mirror * viewport_pixel_aspect;
669 }
670 return quad_transformed;
671}
672
673Array<float2> image_transform_quad_get(const Scene *scene, const Strip *strip, bool apply_rotation)
674{
675 return strip_image_transform_quad_get_ex(scene, strip, apply_rotation);
676}
677
679{
680 return strip_image_transform_quad_get_ex(scene, strip, true);
681}
682
683float2 image_preview_unit_to_px(const Scene *scene, const float2 co_src)
684{
685 return {co_src.x * scene->r.xsch, co_src.y * scene->r.ysch};
686}
687
689{
690 return {co_src.x / scene->r.xsch, co_src.y / scene->r.ysch};
691}
692
694{
695 return {float2(std::numeric_limits<float>::max()), float2(std::numeric_limits<float>::lowest())};
696}
697
700 bool apply_rotation)
701{
703
704 for (Strip *strip : strips) {
705 const Array<float2> quad = image_transform_quad_get(scene, strip, apply_rotation);
706 const Bounds<float2> strip_box = *blender::bounds::min_max(quad.as_span());
707 box = blender::bounds::merge(box, strip_box);
708 }
709
710 return box;
711}
712
713} // namespace blender::seq
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
#define ELEM(...)
eSeqOverlapMode
@ SEQ_OVERLAP_EXPAND
@ SEQ_OVERLAP_SHUFFLE
@ SEQ_OVERLAP_OVERWRITE
#define MAXFRAME
@ SEQ_SINGLE_FRAME_CONTENT
@ SEQ_FLIPX
@ SEQ_IGNORE_CHANNEL_LOCK
@ SEQ_OVERLAP
@ SEQ_FLIPY
@ STRIP_TYPE_MOVIECLIP
@ STRIP_TYPE_IMAGE
@ STRIP_TYPE_MOVIE
@ STRIP_TYPE_EFFECT
@ STRIP_TYPE_META
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:398
constexpr bool is_empty() const
Definition BLI_span.hh:260
constexpr bool contains(const T &value) const
Definition BLI_span.hh:277
bool add(const Key &key)
int64_t remove_if(Predicate &&predicate)
#define SELECT
blender::gpu::Batch * quad
Bounds< T > merge(const Bounds< T > &a, const Bounds< T > &b)
Definition BLI_bounds.hh:26
std::optional< Bounds< T > > min_max(const std::optional< Bounds< T > > &a, const T &b)
Definition BLI_bounds.hh:55
T clamp(const T &a, const T &min, const T &max)
MatT from_origin_transform(const MatT &transform, const VectorT origin)
MatT from_loc_rot_scale(const typename MatT::loc_type &location, const RotationT &rotation, const VecBase< typename MatT::base_type, ScaleDim > &scale)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
Strip * lookup_meta_by_strip(Editing *ed, const Strip *key)
int time_right_handle_frame_get(const Scene *scene, const Strip *strip)
static void strip_transform_handle_overwrite_split(Scene *scene, ListBase *seqbasep, const Strip *transformed, Strip *target)
Array< float2 > image_transform_final_quad_get(const Scene *scene, const Strip *strip)
void relations_invalidate_cache(Scene *scene, Strip *strip)
static void strip_transform_handle_overlap_shuffle(Scene *scene, ListBase *seqbasep, blender::Span< Strip * > transformed_strips, blender::Span< Strip * > time_dependent_strips, bool use_sync_markers)
static void strip_transform_handle_overwrite_trim(Scene *scene, ListBase *seqbasep, const Strip *transformed, Strip *target, const eOvelapDescrition overlap)
SeqTimelineChannel * channel_get_by_index(const ListBase *channels, const int channel_index)
Definition channels.cc:65
ListBase * channels_displayed_get(const Editing *ed)
Definition channels.cc:28
void edit_remove_flagged_strips(Scene *scene, ListBase *seqbase)
static blender::VectorSet< Strip * > query_overwrite_targets(const Scene *scene, ListBase *seqbasep, blender::Span< Strip * > transformed_strips)
Bounds< float2 > image_transform_bounding_box_from_collection(Scene *scene, blender::Span< Strip * > strips, bool apply_rotation)
void edit_flag_for_removal(Scene *scene, ListBase *seqbase, Strip *strip)
float3x3 image_transform_matrix_get(const Scene *scene, const Strip *strip)
void transform_translate_strip(Scene *evil_scene, Strip *strip, int delta)
bool channel_is_locked(const SeqTimelineChannel *channel)
Definition channels.cc:81
VectorSet< Strip * > query_unselected_strips(ListBase *seqbase)
Definition iterator.cc:219
Array< float2 > image_transform_quad_get(const Scene *scene, const Strip *strip, bool apply_rotation)
void strip_channel_set(Strip *strip, int channel)
static void strip_transform_handle_overwrite(Scene *scene, ListBase *seqbasep, blender::Span< Strip * > transformed_strips)
bool transform_test_overlap(const Scene *scene, Strip *strip1, Strip *strip2)
Editing * editing_get(const Scene *scene)
Definition sequencer.cc:272
static blender::VectorSet< Strip * > extract_standalone_strips(blender::Span< Strip * > transformed_strips)
blender::Span< Strip * > SEQ_lookup_effects_by_strip(Editing *ed, const Strip *key)
static eOvelapDescrition overlap_description_get(const Scene *scene, const Strip *transformed, const Strip *target)
int time_left_handle_frame_get(const Scene *, const Strip *strip)
void offset_animdata(const Scene *scene, Strip *strip, float ofs)
Definition animation.cc:42
float2 image_transform_mirror_factor_get(const Strip *strip)
void query_strip_effect_chain(const Scene *scene, Strip *reference_strip, ListBase *seqbase, VectorSet< Strip * > &r_strips)
Definition iterator.cc:231
void strip_time_update_effects_strip_range(const Scene *scene, const blender::Span< Strip * > effects)
bool transform_single_image_check(const Strip *strip)
constexpr int MAX_CHANNELS
void time_update_meta_strip_range(const Scene *scene, Strip *strip_meta)
void iterator_set_expand(const Scene *scene, ListBase *seqbase, VectorSet< Strip * > &strips, void strip_query_func(const Scene *scene, Strip *strip_reference, ListBase *seqbase, VectorSet< Strip * > &strips))
Definition iterator.cc:82
static void strip_transform_handle_expand_to_fit(Scene *scene, ListBase *seqbasep, blender::Span< Strip * > transformed_strips, blender::Span< Strip * > time_dependent_strips, bool use_sync_markers)
void strip_time_translate_handles(const Scene *scene, Strip *strip, const int offset)
bool transform_seqbase_shuffle_ex(ListBase *seqbasep, Strip *test, Scene *evil_scene, int channel_delta)
static bool shuffle_strip_test_overlap(const Scene *scene, const Strip *strip1, const Strip *strip2, const int offset)
void transform_offset_after_frame(Scene *scene, ListBase *seqbase, const int delta, const int timeline_frame)
bool is_valid_strip_channel(const Strip *strip)
Definition sequencer.cc:715
float2 image_transform_origin_offset_pixelspace_get(const Scene *scene, const Strip *strip)
static Array< float2 > strip_image_transform_quad_get_ex(const Scene *scene, const Strip *strip, bool apply_rotation)
static Bounds< float2 > negative_bounds()
static float2 strip_raw_image_size_get(const Scene *scene, const Strip *strip)
VectorSet< Strip * > query_by_reference(Strip *strip_reference, const Scene *scene, ListBase *seqbase, void strip_query_func(const Scene *scene, Strip *strip_reference, ListBase *seqbase, VectorSet< Strip * > &strips))
Definition iterator.cc:69
bool transform_seqbase_shuffle_time(blender::Span< Strip * > strips_to_shuffle, ListBase *seqbasep, Scene *evil_scene, ListBase *markers, const bool use_sync_markers)
bool transform_is_locked(ListBase *channels, const Strip *strip)
static blender::VectorSet< Strip * > query_right_side_strips(const Scene *scene, ListBase *seqbase, blender::Span< Strip * > transformed_strips, blender::Span< Strip * > time_dependent_strips)
bool relation_is_effect_of_strip(const Strip *effect, const Strip *input)
void time_left_handle_frame_set(const Scene *scene, Strip *strip, int timeline_frame)
static int shuffle_strip_time_offset_get(const Scene *scene, blender::Span< Strip * > strips_to_shuffle, ListBase *seqbasep, char dir)
bool channel_is_muted(const SeqTimelineChannel *channel)
Definition channels.cc:86
void transform_handle_overlap(Scene *scene, ListBase *seqbasep, blender::Span< Strip * > transformed_strips, bool use_sync_markers)
void time_right_handle_frame_set(const Scene *scene, Strip *strip, int timeline_frame)
bool transform_strip_can_be_translated(const Strip *strip)
Strip * edit_strip_split(Main *bmain, Scene *scene, ListBase *seqbase, Strip *strip, const int timeline_frame, const eSplitMethod method, const bool ignore_connections, const char **r_error)
float2 image_preview_unit_to_px(const Scene *scene, const float2 co_src)
bool transform_seqbase_shuffle(ListBase *seqbasep, Strip *test, Scene *evil_scene)
eSeqOverlapMode tool_settings_overlap_mode_get(Scene *scene)
Definition sequencer.cc:408
static float3x3 seq_image_transform_matrix_get_ex(const Scene *scene, const Strip *strip, bool apply_rotation=true)
float2 image_preview_unit_from_px(const Scene *scene, const float2 co_src)
int effect_get_num_inputs(int strip_type)
Definition effects.cc:286
VecBase< float, 2 > float2
MatBase< float, 3, 3 > float3x3
void * first
struct ToolSettings * toolsettings
struct Editing * ed
struct RenderData r
ListBase markers
StripCrop * crop
StripTransform * transform
StripElem * stripdata
struct Strip * input1
StripData * data
struct MovieClip * clip
ListBase seqbase
struct Strip * next
struct Strip * input2
i
Definition text_draw.cc:230