Blender V4.5
transform_convert_sequencer.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
10#include "DNA_space_types.h"
11
12#include "MEM_guardedalloc.h"
13
14#include "BLI_listbase.h"
15#include "BLI_math_matrix.h"
16#include "BLI_math_vector.h"
17
18#include "ED_markers.hh"
19
20#include "SEQ_animation.hh"
21#include "SEQ_channels.hh"
22#include "SEQ_iterator.hh"
23#include "SEQ_relations.hh"
24#include "SEQ_sequencer.hh"
25#include "SEQ_time.hh"
26#include "SEQ_transform.hh"
27
28#include "UI_view2d.hh"
29
30#include "transform.hh"
31#include "transform_convert.hh"
32#include "transform_mode.hh"
33
34namespace blender::ed::transform {
35
36#define STRIP_EDGE_PAN_INSIDE_PAD 3.5
37#define STRIP_EDGE_PAN_OUTSIDE_PAD 0 /* Disable clamping for panning, use whole screen. */
38#define STRIP_EDGE_PAN_SPEED_RAMP 1
39#define STRIP_EDGE_PAN_MAX_SPEED 4 /* In UI units per second, slower than default. */
40#define STRIP_EDGE_PAN_DELAY 1.0f
41#define STRIP_EDGE_PAN_ZOOM_INFLUENCE 0.5f
42
43namespace {
44
46struct TransDataSeq {
47 Strip *strip;
49 int flag;
52 int start_offset;
54 short sel_flag;
55};
56
60struct TransSeq {
61 TransDataSeq *tdseq;
62 int selection_channel_range_min;
63 int selection_channel_range_max;
64
65 /* Initial rect of the view2d, used for computing offset during edge panning. */
66 rctf initial_v2d_cur;
67 View2DEdgePanData edge_pan;
68
69 /* Strips that aren't selected, but their position entirely depends on transformed strips. */
70 VectorSet<Strip *> time_dependent_strips;
71};
72
73} // namespace
74
75/* -------------------------------------------------------------------- */
78
79/* This function applies the rules for transforming a strip so duplicate
80 * checks don't need to be added in multiple places.
81 *
82 * count and flag MUST be set.
83 */
84static void SeqTransInfo(TransInfo *t, Strip *strip, int *r_count, int *r_flag)
85{
86 Scene *scene = t->scene;
89
90 /* For extend we need to do some tricks. */
91 if (t->mode == TFM_TIME_EXTEND) {
92
93 /* *** Extend Transform *** */
94 int cfra = scene->r.cfra;
95 int left = seq::time_left_handle_frame_get(scene, strip);
96 int right = seq::time_right_handle_frame_get(scene, strip);
97
98 if ((strip->flag & SELECT) == 0 || seq::transform_is_locked(channels, strip)) {
99 *r_count = 0;
100 *r_flag = 0;
101 }
102 else {
103 *r_count = 1; /* Unless its set to 0, extend will never set 2 handles at once. */
104 *r_flag = (strip->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
105
106 if (t->frame_side == 'R') {
107 if (right <= cfra) {
108 *r_count = *r_flag = 0;
109 } /* Ignore. */
110 else if (left > cfra) {
111 } /* Keep the selection. */
112 else {
113 *r_flag |= SEQ_RIGHTSEL;
114 }
115 }
116 else {
117 if (left >= cfra) {
118 *r_count = *r_flag = 0;
119 } /* Ignore. */
120 else if (right < cfra) {
121 } /* Keep the selection. */
122 else {
123 *r_flag |= SEQ_LEFTSEL;
124 }
125 }
126 }
127 }
128 else {
129
130 t->frame_side = 'B';
131
132 /* *** Normal Transform *** */
133
134 /* Count. */
135
136 /* Non nested strips (reset selection and handles). */
137 if ((strip->flag & SELECT) == 0 || seq::transform_is_locked(channels, strip)) {
138 *r_count = 0;
139 *r_flag = 0;
140 }
141 else {
142 if ((strip->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) == (SEQ_LEFTSEL | SEQ_RIGHTSEL)) {
143 *r_flag = strip->flag;
144 *r_count = 2; /* We need 2 transdata's. */
145 }
146 else {
147 *r_flag = strip->flag;
148 *r_count = 1; /* Selected or with a handle selected. */
149 }
150 }
151 }
152}
153
154static int SeqTransCount(TransInfo *t, ListBase *seqbase)
155{
156 int tot = 0, count, flag;
157
158 LISTBASE_FOREACH (Strip *, strip, seqbase) {
159 SeqTransInfo(t, strip, &count, &flag); /* Ignore the flag. */
160 tot += count;
161 }
162
163 return tot;
164}
165
167 TransData *td,
168 TransData2D *td2d,
169 TransDataSeq *tdsq,
170 Strip *strip,
171 int flag,
172 int sel_flag)
173{
174 int start_left;
175
176 switch (sel_flag) {
177 case SELECT:
178 /* Use seq_tx_get_final_left() and an offset here
179 * so transform has the left hand location of the strip.
180 * `tdsq->start_offset` is used when flushing the tx data back. */
181 start_left = seq::time_left_handle_frame_get(scene, strip);
182 td2d->loc[0] = start_left;
183 tdsq->start_offset = start_left - strip->start; /* Use to apply the original location. */
184 break;
185 case SEQ_LEFTSEL:
186 start_left = seq::time_left_handle_frame_get(scene, strip);
187 td2d->loc[0] = start_left;
188 break;
189 case SEQ_RIGHTSEL:
190 td2d->loc[0] = seq::time_right_handle_frame_get(scene, strip);
191 break;
192 }
193
194 td2d->loc[1] = strip->channel; /* Channel - Y location. */
195 td2d->loc[2] = 0.0f;
196 td2d->loc2d = nullptr;
197
198 tdsq->strip = strip;
199
200 /* Use instead of strip->flag for nested strips and other
201 * cases where the selection may need to be modified. */
202 tdsq->flag = flag;
203 tdsq->sel_flag = sel_flag;
204
205 td->extra = (void *)tdsq; /* Allow us to update the strip from here. */
206
207 td->flag = 0;
208 td->loc = td2d->loc;
209 copy_v3_v3(td->center, td->loc);
210 copy_v3_v3(td->iloc, td->loc);
211
212 memset(td->axismtx, 0, sizeof(td->axismtx));
213 td->axismtx[2][2] = 1.0f;
214
215 td->ext = nullptr;
216 td->val = nullptr;
217
218 td->flag |= TD_SELECTED;
219 td->dist = 0.0;
220
221 unit_m3(td->mtx);
222 unit_m3(td->smtx);
223
224 /* Time Transform (extend). */
225 td->val = td2d->loc;
226 td->ival = td2d->loc[0];
227
228 return td;
229}
230
232 TransInfo *t, ListBase *seqbase, TransData *td, TransData2D *td2d, TransDataSeq *tdsq)
233{
234 Scene *scene = t->scene;
235 int count, flag;
236 int tot = 0;
237
238 LISTBASE_FOREACH (Strip *, strip, seqbase) {
239
240 SeqTransInfo(t, strip, &count, &flag);
241
242 /* Use 'flag' which is derived from strip->flag but modified for special cases. */
243 if (flag & SELECT) {
244 if (flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) {
245 if (flag & SEQ_LEFTSEL) {
246 SeqToTransData(scene, td++, td2d++, tdsq++, strip, flag, SEQ_LEFTSEL);
247 tot++;
248 }
249 if (flag & SEQ_RIGHTSEL) {
250 SeqToTransData(scene, td++, td2d++, tdsq++, strip, flag, SEQ_RIGHTSEL);
251 tot++;
252 }
253 }
254 else {
255 SeqToTransData(scene, td++, td2d++, tdsq++, strip, flag, SELECT);
256 tot++;
257 }
258 }
259 }
260 return tot;
261}
262
264{
265 if ((custom_data->data != nullptr) && custom_data->use_free) {
266 TransSeq *ts = static_cast<TransSeq *>(custom_data->data);
267 MEM_freeN(ts->tdseq);
268 MEM_delete(ts);
269 custom_data->data = nullptr;
270 }
271}
272
273/* Canceled, need to update the strips display. */
274static void seq_transform_cancel(TransInfo *t, Span<Strip *> transformed_strips)
275{
277
278 for (Strip *strip : transformed_strips) {
279 /* Handle pre-existing overlapping strips even when operator is canceled.
280 * This is necessary for #SEQUENCER_OT_duplicate_move macro for example. */
281 if (seq::transform_test_overlap(t->scene, seqbase, strip)) {
282 seq::transform_seqbase_shuffle(seqbase, strip, t->scene);
283 }
284 }
285}
286
292
294{
295 for (Strip *strip : transformed_strips) {
296 if (strip->flag & SEQ_OVERLAP) {
297 return true;
298 }
299 }
300 return false;
301}
302
304{
305 VectorSet<Strip *> strips;
306 TransData *td = tc->data;
307 for (int a = 0; a < tc->data_len; a++, td++) {
308 Strip *strip = ((TransDataSeq *)td->extra)->strip;
309 strips.add(strip);
310 }
311 return strips;
312}
313
314static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data)
315{
317 if (ed == nullptr) {
318 free_transform_custom_data(custom_data);
319 return;
320 }
321
322 VectorSet transformed_strips = seq_transform_collection_from_transdata(tc);
324 t->scene, seqbase_active_get(t), transformed_strips, seq::query_strip_effect_chain);
325
326 for (Strip *strip : transformed_strips) {
327 strip->flag &= ~SEQ_IGNORE_CHANNEL_LOCK;
328 }
329
330 if (t->state == TRANS_CANCEL) {
331 seq_transform_cancel(t, transformed_strips);
332 free_transform_custom_data(custom_data);
333 return;
334 }
335
336 TransSeq *ts = static_cast<TransSeq *>(tc->custom.type.data);
337 ListBase *seqbasep = seqbase_active_get(t);
338 Scene *scene = t->scene;
339 const bool use_sync_markers = (((SpaceSeq *)t->area->spacedata.first)->flag &
340 SEQ_MARKER_TRANS) != 0;
341 if (seq_transform_check_overlap(transformed_strips)) {
343 scene, seqbasep, transformed_strips, ts->time_dependent_strips, use_sync_markers);
344 }
345
347 free_transform_custom_data(custom_data);
348}
349
351{
352 VectorSet<Strip *> strips;
353 LISTBASE_FOREACH (Strip *, strip, seqbase) {
354 if ((strip->flag & SELECT) != 0 && ((strip->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) == 0)) {
355 strips.add(strip);
356 }
357 }
358 return strips;
359}
360
365
366static Strip *effect_input_get(const Scene *scene, Strip *effect, SeqInputSide side)
367{
368 Strip *input = effect->input1;
369 if (effect->input2 && (seq::time_left_handle_frame_get(scene, effect->input2) -
370 seq::time_left_handle_frame_get(scene, effect->input1)) *
371 side >
372 0)
373 {
374 input = effect->input2;
375 }
376 return input;
377}
378
379static Strip *effect_base_input_get(const Scene *scene, Strip *effect, SeqInputSide side)
380{
381 Strip *input = effect, *strip_iter = effect;
382 while (strip_iter != nullptr) {
383 input = strip_iter;
384 strip_iter = effect_input_get(scene, strip_iter, side);
385 }
386 return input;
387}
388
394 VectorSet<Strip *> &time_dependent_strips)
395{
396 ListBase *seqbase = seqbase_active_get(t);
397
398 /* Query dependent strips where used strips do not have handles selected.
399 * If all inputs of any effect even indirectly(through another effect) points to selected strip,
400 * its position will change. */
401
402 VectorSet<Strip *> strips_no_handles = query_selected_strips_no_handles(seqbase);
403 time_dependent_strips.add_multiple(strips_no_handles);
404
405 seq::iterator_set_expand(t->scene, seqbase, strips_no_handles, seq::query_strip_effect_chain);
406 bool strip_added = true;
407
408 while (strip_added) {
409 strip_added = false;
410
411 for (Strip *strip : strips_no_handles) {
412 if (time_dependent_strips.contains(strip)) {
413 continue; /* Strip is already in collection, skip it. */
414 }
415
416 /* If both input1 and input2 exist, both must be selected. */
417 if (strip->input1 && time_dependent_strips.contains(strip->input1)) {
418 if (strip->input2 && !time_dependent_strips.contains(strip->input2)) {
419 continue;
420 }
421 strip_added = true;
422 time_dependent_strips.add(strip);
423 }
424 }
425 }
426
427 /* Query dependent strips where used strips do have handles selected.
428 * If any 2-input effect changes position because handles were moved, animation should be offset.
429 * With single input effect, it is less likely desirable to move animation. */
430
431 VectorSet selected_strips = seq::query_selected_strips(seqbase);
432 seq::iterator_set_expand(t->scene, seqbase, selected_strips, seq::query_strip_effect_chain);
433 for (Strip *strip : selected_strips) {
434 /* Check only 2 input effects. */
435 if (strip->input1 == nullptr || strip->input2 == nullptr) {
436 continue;
437 }
438
439 /* Find immediate base inputs(left and right side). */
440 Strip *input_left = effect_base_input_get(t->scene, strip, SEQ_INPUT_LEFT);
441 Strip *input_right = effect_base_input_get(t->scene, strip, SEQ_INPUT_RIGHT);
442
443 if ((input_left->flag & SEQ_RIGHTSEL) != 0 && (input_right->flag & SEQ_LEFTSEL) != 0) {
444 time_dependent_strips.add(strip);
445 }
446 }
447
448 /* Remove all non-effects. */
449 time_dependent_strips.remove_if(
450 [&](Strip *strip) { return seq::transform_strip_can_be_translated(strip); });
451}
452
453static void createTransSeqData(bContext * /*C*/, TransInfo *t)
454{
455 Scene *scene = t->scene;
457 TransData *td = nullptr;
458 TransData2D *td2d = nullptr;
459 TransDataSeq *tdsq = nullptr;
460 TransSeq *ts = nullptr;
461
462 int count = 0;
463
465
466 if (ed == nullptr) {
467 tc->data_len = 0;
468 return;
469 }
470
471 /* Disable cursor wrapping for edge pan. */
472 if (t->mode == TFM_TRANSLATION) {
474 }
475
478
479 count = SeqTransCount(t, ed->seqbasep);
480
481 /* Allocate memory for data. */
482 tc->data_len = count;
483
484 /* Stop if trying to build list if nothing selected. */
485 if (count == 0) {
486 return;
487 }
488
489 tc->custom.type.data = ts = MEM_new<TransSeq>(__func__);
490 tc->custom.type.use_free = true;
491 td = tc->data = MEM_calloc_arrayN<TransData>(tc->data_len, "TransSeq TransData");
492 td2d = tc->data_2d = MEM_calloc_arrayN<TransData2D>(tc->data_len, "TransSeq TransData2D");
493 ts->tdseq = tdsq = MEM_calloc_arrayN<TransDataSeq>(tc->data_len, "TransSeq TransDataSeq");
494
495 /* Custom data to enable edge panning during transformation. */
497 &ts->edge_pan,
505 ts->initial_v2d_cur = t->region->v2d.cur;
506
507 /* Loop 2: build transdata array. */
508 SeqToTransData_build(t, ed->seqbasep, td, td2d, tdsq);
509
510 ts->selection_channel_range_min = seq::MAX_CHANNELS + 1;
512 if ((strip->flag & SELECT) != 0) {
513 ts->selection_channel_range_min = min_ii(ts->selection_channel_range_min, strip->channel);
514 ts->selection_channel_range_max = max_ii(ts->selection_channel_range_max, strip->channel);
515 }
516 }
517
518 query_time_dependent_strips_strips(t, ts->time_dependent_strips);
519}
520
522
523/* -------------------------------------------------------------------- */
526
527static void view2d_edge_pan_loc_compensate(TransInfo *t, float offset[2])
528{
529 TransSeq *ts = (TransSeq *)TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->custom.type.data;
530
531 const rctf rect_prev = t->region->v2d.cur;
532
533 if (t->options & CTX_VIEW2D_EDGE_PAN) {
534 if (t->state == TRANS_CANCEL) {
535 UI_view2d_edge_pan_cancel(t->context, &ts->edge_pan);
536 }
537 else {
538 /* Edge panning functions expect window coordinates, mval is relative to region. */
539 const int xy[2] = {
540 t->region->winrct.xmin + int(t->mval[0]),
541 t->region->winrct.ymin + int(t->mval[1]),
542 };
543 UI_view2d_edge_pan_apply(t->context, &ts->edge_pan, xy);
544 }
545 }
546
547 if (t->state != TRANS_CANCEL) {
548 if (!BLI_rctf_compare(&rect_prev, &t->region->v2d.cur, FLT_EPSILON)) {
549 /* Additional offset due to change in view2D rect. */
550 BLI_rctf_transform_pt_v(&t->region->v2d.cur, &rect_prev, offset, offset);
552 }
553 }
554}
555
557{
558 /* Editing null check already done. */
559 ListBase *seqbasep = seqbase_active_get(t);
560
561 int a, new_frame, offset;
562
563 TransData *td = nullptr;
564 TransData2D *td2d = nullptr;
565 TransDataSeq *tdsq = nullptr;
566 Strip *strip;
567
568 Scene *scene = t->scene;
569
571
572 /* This is calculated for offsetting animation of effects that change position with inputs.
573 * Maximum(positive or negative) value is used, because individual strips can be clamped. This
574 * works fairly well in most scenarios, but there can be some edge cases.
575 *
576 * Better solution would be to store effect position and calculate real offset. However with many
577 * (>5) effects in chain, there is visible lag in strip position update, because during
578 * recalculation, hierarchy is not taken into account. */
579 int max_offset = 0;
580
581 float edge_pan_offset[2] = {0.0f, 0.0f};
582 view2d_edge_pan_loc_compensate(t, edge_pan_offset);
583
584 /* Flush to 2D vector from internally used 3D vector. */
585 for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) {
586 tdsq = (TransDataSeq *)td->extra;
587 strip = tdsq->strip;
588
589 new_frame = round_fl_to_int(td->loc[0] + edge_pan_offset[0]);
590
591 switch (tdsq->sel_flag) {
592 case SELECT: {
594 offset = new_frame - tdsq->start_offset - strip->start;
595 seq::transform_translate_strip(scene, strip, offset);
596 if (abs(offset) > abs(max_offset)) {
597 max_offset = offset;
598 }
599 }
600 seq::strip_channel_set(strip, round_fl_to_int(td->loc[1] + edge_pan_offset[1]));
601 break;
602 }
603 case SEQ_LEFTSEL: { /* No vertical transform. */
604 /* Update right handle first if both handles are selected and the new_frame is right of
605 * the old one to avoid unexpected left handle clamping when canceling. See #126191. */
606 bool both_handles_selected = (tdsq->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) ==
608 if (both_handles_selected && new_frame > seq::time_left_handle_frame_get(scene, strip)) {
609 a++, td++, td2d++;
610 int new_right_frame = round_fl_to_int(td->loc[0] + edge_pan_offset[0]);
611 seq::time_right_handle_frame_set(scene, strip, new_right_frame);
612 }
613 int old_startdisp = seq::time_left_handle_frame_get(scene, strip);
614 seq::time_left_handle_frame_set(t->scene, strip, new_frame);
615
616 if (abs(seq::time_left_handle_frame_get(scene, strip) - old_startdisp) > abs(max_offset)) {
617 max_offset = seq::time_left_handle_frame_get(scene, strip) - old_startdisp;
618 }
619 break;
620 }
621 case SEQ_RIGHTSEL: { /* No vertical transform. */
622 int old_enddisp = seq::time_right_handle_frame_get(scene, strip);
623 seq::time_right_handle_frame_set(t->scene, strip, new_frame);
624
625 if (abs(seq::time_right_handle_frame_get(scene, strip) - old_enddisp) > abs(max_offset)) {
626 max_offset = seq::time_right_handle_frame_get(scene, strip) - old_enddisp;
627 }
628 break;
629 }
630 }
631 }
632
633 TransSeq *ts = (TransSeq *)TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->custom.type.data;
634
635 /* Update animation for effects. */
636 for (Strip *strip : ts->time_dependent_strips) {
637 seq::offset_animdata(t->scene, strip, max_offset);
638 }
639
640 /* Need to do the overlap check in a new loop otherwise adjacent strips
641 * will not be updated and we'll get false positives. */
642 VectorSet transformed_strips = seq_transform_collection_from_transdata(tc);
644 t->scene, seqbase_active_get(t), transformed_strips, seq::query_strip_effect_chain);
645
646 for (Strip *strip : transformed_strips) {
647 /* Test overlap, displays red outline. */
648 strip->flag &= ~SEQ_OVERLAP;
649 if (seq::transform_test_overlap(scene, seqbasep, strip)) {
650 strip->flag |= SEQ_OVERLAP;
651 }
652 }
653}
654
656{
657 TransData *td;
658 int a;
659 Strip *strip_prev = nullptr;
660
662
663 for (a = 0, td = tc->data; a < tc->data_len; a++, td++) {
664 TransDataSeq *tdsq = (TransDataSeq *)td->extra;
665 Strip *strip = tdsq->strip;
666
667 if (strip != strip_prev) {
669 }
670
671 strip_prev = strip;
672 }
673
675
676 flushTransSeq(t);
677}
678
680
681/* -------------------------------------------------------------------- */
684
686{
687 SpaceSeq *sseq = (SpaceSeq *)t->area->spacedata.first;
688 if ((sseq->flag & SPACE_SEQ_DESELECT_STRIP_HANDLE) != 0 &&
690 {
693 for (Strip *strip : strips) {
694 strip->flag &= ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
695 }
696 }
697
699
700 /* #freeSeqData in `transform_conversions.cc` does this
701 * keep here so the else at the end won't run. */
702 if (t->state == TRANS_CANCEL) {
703 return;
704 }
705
706 /* Marker transform, not especially nice but we may want to move markers
707 * at the same time as strips in the Video Sequencer. */
708 if (sseq->flag & SEQ_MARKER_TRANS) {
709 /* Can't use #TFM_TIME_EXTEND
710 * for some reason EXTEND is changed into TRANSLATE, so use frame_side instead. */
711
712 if (t->mode == TFM_SEQ_SLIDE) {
713 if (t->frame_side == 'B') {
716 }
717 }
718 else if (ELEM(t->frame_side, 'L', 'R')) {
721 }
722 }
723}
724
726{
727 const TransSeq *ts = (TransSeq *)TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->custom.type.data;
728 const int channel_offset = round_fl_to_int(r_val[1]);
729 const int min_channel_after_transform = ts->selection_channel_range_min + channel_offset;
730 const int max_channel_after_transform = ts->selection_channel_range_max + channel_offset;
731
732 if (max_channel_after_transform > seq::MAX_CHANNELS) {
733 r_val[1] -= max_channel_after_transform - seq::MAX_CHANNELS;
734 }
735 if (min_channel_after_transform < 1) {
736 r_val[1] -= min_channel_after_transform - 1;
737 }
738}
739
741
743 /*flags*/ (T_POINTS | T_2D_EDIT),
744 /*create_trans_data*/ createTransSeqData,
745 /*recalc_data*/ recalcData_sequencer,
746 /*special_aftertrans_update*/ special_aftertrans_update__sequencer,
747};
748
749} // namespace blender::ed::transform
#define LISTBASE_FOREACH(type, var, list)
MINLINE int round_fl_to_int(float a)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
void unit_m3(float m[3][3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
void BLI_rctf_transform_pt_v(const rctf *dst, const rctf *src, float xy_dst[2], const float xy_src[2])
Definition rct.cc:526
bool BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, float limit)
#define ELEM(...)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_SEQUENCER_STRIPS
Definition DNA_ID.h:1030
@ SEQ_RIGHTSEL
@ SEQ_IGNORE_CHANNEL_LOCK
@ SEQ_OVERLAP
@ SEQ_LEFTSEL
@ SPACE_SEQ_DESELECT_STRIP_HANDLE
@ SEQ_MARKER_TRANS
Read Guarded memory(de)allocation.
void UI_view2d_edge_pan_set_limits(View2DEdgePanData *vpd, float xmin, float xmax, float ymin, float ymax)
void UI_view2d_edge_pan_cancel(bContext *C, View2DEdgePanData *vpd)
void UI_view2d_edge_pan_init(bContext *C, View2DEdgePanData *vpd, float inside_pad, float outside_pad, float speed_ramp, float max_speed, float delay, float zoom_influence)
void UI_view2d_edge_pan_apply(bContext *C, View2DEdgePanData *vpd, const int xy[2]) ATTR_NONNULL(1
int ED_markers_post_apply_transform(ListBase *markers, Scene *scene, int mode, float value, char side)
bool add(const Key &key)
void add_multiple(Span< Key > keys)
bool contains(const Key &key) const
int64_t remove_if(Predicate &&predicate)
#define SELECT
#define input
#define abs
int count
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static int left
static void free_transform_custom_data(TransCustomData *custom_data)
TransConvertTypeInfo TransConvertType_Sequencer
static void query_time_dependent_strips_strips(TransInfo *t, VectorSet< Strip * > &time_dependent_strips)
static void view2d_edge_pan_loc_compensate(TransInfo *t, float offset[2])
static void flushTransSeq(TransInfo *t)
char transform_convert_frame_side_dir_get(TransInfo *t, float cframe)
static TransData * SeqToTransData(Scene *scene, TransData *td, TransData2D *td2d, TransDataSeq *tdsq, Strip *strip, int flag, int sel_flag)
static void createTransSeqData(bContext *, TransInfo *t)
static void seq_transform_cancel(TransInfo *t, Span< Strip * > transformed_strips)
static Strip * effect_base_input_get(const Scene *scene, Strip *effect, SeqInputSide side)
static void special_aftertrans_update__sequencer(bContext *, TransInfo *t)
bool transform_mode_edge_seq_slide_use_restore_handle_selection(const TransInfo *t)
static VectorSet< Strip * > seq_transform_collection_from_transdata(TransDataContainer *tc)
static void SeqTransInfo(TransInfo *t, Strip *strip, int *r_count, int *r_flag)
void transformViewUpdate(TransInfo *t)
void transform_convert_sequencer_channel_clamp(TransInfo *t, float r_val[2])
static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data)
static void recalcData_sequencer(TransInfo *t)
static VectorSet< Strip * > query_selected_strips_no_handles(ListBase *seqbase)
static int SeqTransCount(TransInfo *t, ListBase *seqbase)
static Strip * effect_input_get(const Scene *scene, Strip *effect, SeqInputSide side)
static int SeqToTransData_build(TransInfo *t, ListBase *seqbase, TransData *td, TransData2D *td2d, TransDataSeq *tdsq)
bool seq_transform_check_overlap(Span< Strip * > transformed_strips)
static ListBase * seqbase_active_get(const TransInfo *t)
int time_right_handle_frame_get(const Scene *scene, const Strip *strip)
void relations_invalidate_cache(Scene *scene, Strip *strip)
ListBase * channels_displayed_get(const Editing *ed)
Definition channels.cc:28
VectorSet< Strip * > query_selected_strips(ListBase *seqbase)
Definition iterator.cc:127
void transform_translate_strip(Scene *evil_scene, Strip *strip, int delta)
void strip_channel_set(Strip *strip, int channel)
bool transform_test_overlap(const Scene *scene, Strip *strip1, Strip *strip2)
Editing * editing_get(const Scene *scene)
Definition sequencer.cc:272
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
void query_strip_effect_chain(const Scene *scene, Strip *reference_strip, ListBase *seqbase, VectorSet< Strip * > &r_strips)
Definition iterator.cc:231
constexpr int MAX_CHANNELS
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
bool transform_is_locked(ListBase *channels, const Strip *strip)
void time_left_handle_frame_set(const Scene *scene, Strip *strip, int timeline_frame)
void transform_handle_overlap(Scene *scene, ListBase *seqbasep, blender::Span< Strip * > transformed_strips, bool use_sync_markers)
ListBase * active_seqbase_get(const Editing *ed)
Definition sequencer.cc:420
void time_right_handle_frame_set(const Scene *scene, Strip *strip, int timeline_frame)
bool transform_strip_can_be_translated(const Strip *strip)
bool transform_seqbase_shuffle(ListBase *seqbasep, Strip *test, Scene *evil_scene)
#define FLT_MAX
Definition stdcycles.h:14
void * first
struct RenderData r
ListBase markers
ListBase spacedata
struct Strip * input1
struct Strip * input2
void(* free_cb)(TransInfo *, TransDataContainer *tc, TransCustomData *custom_data)
Definition transform.hh:628
int ymin
int xmin
#define TRANS_DATA_CONTAINER_FIRST_SINGLE(t)
Definition transform.hh:39
conversion and adaptation of different datablocks to a common struct.
#define STRIP_EDGE_PAN_OUTSIDE_PAD
#define STRIP_EDGE_PAN_SPEED_RAMP
#define STRIP_EDGE_PAN_INSIDE_PAD
#define STRIP_EDGE_PAN_MAX_SPEED
#define STRIP_EDGE_PAN_DELAY
#define STRIP_EDGE_PAN_ZOOM_INFLUENCE
transform modes used by different operators.
int xy[2]
Definition wm_draw.cc:174
uint8_t flag
Definition wm_window.cc:139