Blender V5.0
transform_snap_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
9#include <cstddef>
10#include <cstdlib>
11
12#include "BLI_assert.h"
13#include "BLI_listbase.h"
14#include "BLI_map.hh"
15#include "BLI_math_base.h"
16#include "BLI_math_vector.h"
17#include "BLI_math_vector.hh"
18#include "BLI_vector.hh"
19
20#include "MEM_guardedalloc.h"
21
22#include "DNA_scene_types.h"
23#include "DNA_screen_types.h"
24#include "DNA_sequence_types.h"
25#include "DNA_space_types.h"
26
27#include "ED_transform.hh"
28
29#include "UI_view2d.hh"
30
31#include "SEQ_channels.hh"
32#include "SEQ_effects.hh"
33#include "SEQ_iterator.hh"
34#include "SEQ_relations.hh"
35#include "SEQ_render.hh"
36#include "SEQ_retiming.hh"
37#include "SEQ_sequencer.hh"
38#include "SEQ_time.hh"
39#include "SEQ_transform.hh"
40
41#include "transform.hh"
42#include "transform_convert.hh"
43#include "transform_snap.hh"
44
45namespace blender::ed::transform {
46
50
51 MEM_CXX_CLASS_ALLOC_FUNCS("TransSeqSnapData")
52};
53
54/* -------------------------------------------------------------------- */
57
59 const Scene *scene, Map<SeqRetimingKey *, Strip *> &retiming_selection)
60{
61 VectorSet<Strip *> snap_sources;
62
64 snap_sources = seq::query_selected_strips(seqbase);
65
66 /* Add strips owned by retiming keys to exclude these from targets */
67 for (Strip *strip : retiming_selection.values()) {
68 snap_sources.add(strip);
69 }
70
71 return snap_sources;
72}
73
75{
76 VectorSet<Strip *> snap_sources;
77
78 Editing *ed = seq::editing_get(scene);
80
81 snap_sources = seq::query_rendered_strips(
82 scene, channels, ed->current_strips(), scene->r.cfra, 0);
83 snap_sources.remove_if([&](Strip *strip) { return (strip->flag & SELECT) == 0; });
84
85 return snap_sources;
86}
87
88static int cmp_fn(const void *a, const void *b)
89{
90 return round_fl_to_int((*(float2 *)a)[0] - (*(float2 *)b)[0]);
91}
92
94 TransSeqSnapData *snap_data,
95 const Span<Strip *> snap_sources)
96{
97 for (Strip *strip : snap_sources) {
98 int left = 0, right = 0;
99 if (strip->flag & SEQ_LEFTSEL && !(strip->flag & SEQ_RIGHTSEL)) {
100 left = right = seq::time_left_handle_frame_get(scene, strip);
101 }
102 else if (strip->flag & SEQ_RIGHTSEL && !(strip->flag & SEQ_LEFTSEL)) {
103 left = right = seq::time_right_handle_frame_get(scene, strip);
104 }
105 else {
107 right = seq::time_right_handle_frame_get(scene, strip);
108 }
109
110 /* Set only the x-positions when snapping in the timeline. */
111 snap_data->source_snap_points.append(float2(left));
112 snap_data->source_snap_points.append(float2(right));
113 }
114
115 qsort(snap_data->source_snap_points.data(),
116 snap_data->source_snap_points.size(),
117 sizeof(float2),
118 cmp_fn);
119}
120
122 const Scene *scene,
123 TransSeqSnapData *snap_data,
124 const Map<SeqRetimingKey *, Strip *> &retiming_selection)
125{
126 for (auto item : retiming_selection.items()) {
127 const int key_frame = seq::retiming_key_timeline_frame_get(scene, item.value, item.key);
128 snap_data->source_snap_points.append(float2(key_frame));
129 }
130
131 qsort(snap_data->source_snap_points.data(),
132 snap_data->source_snap_points.size(),
133 sizeof(float2),
134 cmp_fn);
135}
136
138 TransSeqSnapData *snap_data,
139 const Span<Strip *> snap_sources)
140{
141 for (Strip *strip : snap_sources) {
142 const Array<float2> strip_image_quad = seq::image_transform_final_quad_get(scene, strip);
143
144 for (int i = 0; i < 4; i++) {
145 snap_data->source_snap_points.append(strip_image_quad[i]);
146 }
147
148 /* Add origins last */
149 const float2 image_origin = seq::image_transform_origin_offset_pixelspace_get(scene, strip);
150 snap_data->source_snap_points.append(image_origin);
151 }
152}
153
155 TransSeqSnapData *snap_data,
156 const Span<Strip *> snap_sources)
157{
158
159 const size_t point_count_source = snap_sources.size();
160
161 if (point_count_source == 0) {
162 return;
163 }
164
165 snap_data->source_snap_points.reinitialize(point_count_source);
166 int i = 0;
167 for (Strip *strip : snap_sources) {
168 /* Add origins last */
170 snap_data->source_snap_points[i][0] = image_origin[0];
171 snap_data->source_snap_points[i][1] = image_origin[1];
172 i++;
173 }
174
175 BLI_assert(i <= snap_data->source_snap_points.size());
176}
177
179
180/* -------------------------------------------------------------------- */
183
184/* Add effect strips directly or indirectly connected to `strip_reference` to `collection`. */
185static void query_strip_effects_fn(const Scene *scene,
186 Strip *strip_reference,
187 ListBase *seqbase,
188 VectorSet<Strip *> &strips)
189{
190 if (strips.contains(strip_reference)) {
191 return; /* Strip is already in set, so all effects connected to it are as well. */
192 }
193 strips.add(strip_reference);
194
195 /* Find all strips connected to `strip_reference`. */
196 LISTBASE_FOREACH (Strip *, strip_test, seqbase) {
197 if (seq::relation_is_effect_of_strip(strip_test, strip_reference)) {
198 query_strip_effects_fn(scene, strip_test, seqbase, strips);
199 }
200 }
201}
202
204 const Span<Strip *> snap_sources,
205 const bool exclude_selected)
206{
207 Editing *ed = seq::editing_get(scene);
210 const short snap_flag = seq::tool_settings_snap_flag_get(scene);
211
212 /* Effects will always change position with strip to which they are connected and they don't
213 * have to be selected. Remove such strips from `snap_targets` collection. */
214 VectorSet effects_of_snap_sources = snap_sources;
215 seq::iterator_set_expand(scene, seqbase, effects_of_snap_sources, query_strip_effects_fn);
216 effects_of_snap_sources.remove_if([&](Strip *strip) {
217 return strip->is_effect() && seq::effect_get_num_inputs(strip->type) == 0;
218 });
219
220 VectorSet<Strip *> snap_targets;
221 LISTBASE_FOREACH (Strip *, strip, seqbase) {
222 if (exclude_selected && strip->flag & SELECT) {
223 continue; /* Selected are being transformed if there is no drag and drop. */
224 }
225 if (seq::render_is_muted(channels, strip) && (snap_flag & SEQ_SNAP_IGNORE_MUTED)) {
226 continue;
227 }
228 if (strip->type == STRIP_TYPE_SOUND_RAM && (snap_flag & SEQ_SNAP_IGNORE_SOUND)) {
229 continue;
230 }
231 if (effects_of_snap_sources.contains(strip)) {
232 continue;
233 }
234
235 snap_targets.add(strip);
236 }
237
238 return snap_targets;
239}
240
242{
243 Scene *scene = t->scene;
244 short snap_mode = t->tsnap.mode;
245
246 VectorSet<Strip *> snap_targets;
247
248 /* We don't need to calculate strip snap targets if the option is unselected. */
249 if ((snap_mode & SEQ_SNAP_TO_STRIPS_PREVIEW) == 0) {
250 return snap_targets;
251 }
252
253 Editing *ed = seq::editing_get(scene);
255
256 snap_targets = seq::query_rendered_strips(
257 scene, channels, ed->current_strips(), scene->r.cfra, 0);
258
259 /* Selected strips are only valid targets when snapping the cursor or origin. */
260 if ((t->data_type == &TransConvertType_SequencerImage) && (t->flag & T_ORIGIN) == 0) {
261 snap_targets.remove_if([&](Strip *strip) { return (strip->flag & SELECT) != 0; });
262 }
263
264 return snap_targets;
265}
266
268 Span<Strip *> snap_strip_targets)
269{
271
272 for (Strip *strip : snap_strip_targets) {
273 for (SeqRetimingKey &key : seq::retiming_keys_get(strip)) {
274 const int key_frame = seq::retiming_key_timeline_frame_get(scene, strip, &key);
275 if (seq::time_strip_intersects_frame(scene, strip, key_frame)) {
276 visible_keys.add(&key, strip);
277 }
278 }
279 }
280
281 return visible_keys;
282}
283
284static void points_build_targets_timeline(const Scene *scene,
285 const short snap_mode,
286 TransSeqSnapData *snap_data,
287 const Span<Strip *> strip_targets)
288{
289 if (snap_mode & SEQ_SNAP_TO_CURRENT_FRAME) {
290 snap_data->target_snap_points.append(float2(scene->r.cfra));
291 }
292
293 if (snap_mode & SEQ_SNAP_TO_MARKERS) {
294 LISTBASE_FOREACH (TimeMarker *, marker, &scene->markers) {
295 snap_data->target_snap_points.append(float2(marker->frame));
296 }
297 }
298
299 if (snap_mode & SEQ_SNAP_TO_FRAME_RANGE) {
300 snap_data->target_snap_points.append(float2(PSFRA));
301 snap_data->target_snap_points.append(float2(PEFRA + 1));
302 }
303
304 for (Strip *strip : strip_targets) {
305 snap_data->target_snap_points.append(float2(seq::time_left_handle_frame_get(scene, strip)));
306 snap_data->target_snap_points.append(float2(seq::time_right_handle_frame_get(scene, strip)));
307
308 if (snap_mode & SEQ_SNAP_TO_STRIP_HOLD) {
309 int content_start = seq::time_start_frame_get(strip);
310 int content_end = seq::time_content_end_frame_get(scene, strip);
311
312 /* Effects and single image strips produce incorrect content length. Skip these strips. */
313 if (strip->is_effect() || strip->len == 1) {
314 content_start = seq::time_left_handle_frame_get(scene, strip);
315 content_end = seq::time_right_handle_frame_get(scene, strip);
316 }
317
318 CLAMP(content_start,
321 CLAMP(content_end,
324
325 snap_data->target_snap_points.append(float2(content_start));
326 snap_data->target_snap_points.append(float2(content_end));
327 }
328 }
329
330 Map retiming_key_targets = visible_retiming_keys_get(scene, strip_targets);
331 if (snap_mode & SEQ_SNAP_TO_RETIMING) {
332 for (auto item : retiming_key_targets.items()) {
333 const int key_frame = seq::retiming_key_timeline_frame_get(scene, item.value, item.key);
334 snap_data->target_snap_points.append(float2(key_frame));
335 }
336 }
337
338 qsort(snap_data->target_snap_points.data(),
339 snap_data->target_snap_points.size(),
340 sizeof(float2),
341 cmp_fn);
342}
343
345 const short snap_mode,
346 TransSeqSnapData *snap_data)
347{
348 if (snap_mode & SEQ_SNAP_TO_PREVIEW_BORDERS) {
349 snap_data->target_snap_points.append(float2(v2d->tot.xmin, v2d->tot.ymin));
350 snap_data->target_snap_points.append(float2(v2d->tot.xmax, v2d->tot.ymax));
351 snap_data->target_snap_points.append(float2(v2d->tot.xmin, v2d->tot.ymax));
352 snap_data->target_snap_points.append(float2(v2d->tot.xmax, v2d->tot.ymin));
353 }
354
355 if (snap_mode & SEQ_SNAP_TO_PREVIEW_CENTER) {
356 snap_data->target_snap_points.append(float2(0));
357 }
358}
359
361 const View2D *v2d,
362 const short snap_mode,
363 TransSeqSnapData *snap_data,
364 const Span<Strip *> snap_targets)
365{
366 points_build_targets_preview_general(v2d, snap_mode, snap_data);
367
368 if (snap_mode & SEQ_SNAP_TO_STRIPS_PREVIEW) {
369 for (Strip *strip : snap_targets) {
370 const Array<float2> strip_image_quad = seq::image_transform_final_quad_get(scene, strip);
371
372 for (int i = 0; i < 4; i++) {
373 snap_data->target_snap_points.append(strip_image_quad[i]);
374 }
375
376 const float2 image_origin = seq::image_transform_origin_offset_pixelspace_get(scene, strip);
377 snap_data->target_snap_points.append(image_origin);
378 }
379 }
380}
381
382static void points_build_3x3_grid(const Scene *scene, TransSeqSnapData *snap_data, Strip *strip)
383{
384 const Array<float2> strip_image_quad = seq::image_transform_final_quad_get(scene, strip);
385 /* Corners. */
386 for (int i = 0; i < 4; i++) {
387 snap_data->target_snap_points.append(strip_image_quad[i]);
388 }
389
390 /* Middle top, bottom and center of the image. */
391 const float2 tm = blender::math::interpolate(strip_image_quad[0], strip_image_quad[3], 0.5f);
392 const float2 bm = blender::math::interpolate(strip_image_quad[1], strip_image_quad[2], 0.5f);
393 const float2 mm = blender::math::interpolate(bm, tm, 0.5f);
394 snap_data->target_snap_points.append(tm);
395 snap_data->target_snap_points.append(mm);
396 snap_data->target_snap_points.append(bm);
397 /* Left and right. */
398 snap_data->target_snap_points.append(
399 blender::math::interpolate(strip_image_quad[2], strip_image_quad[3], 0.5f));
400 snap_data->target_snap_points.append(
401 blender::math::interpolate(strip_image_quad[0], strip_image_quad[1], 0.5f));
402}
403
405 TransSeqSnapData *snap_data,
406 const Span<Strip *> snap_sources,
407 const Span<Strip *> snap_targets)
408{
409 for (Strip *strip : snap_sources) {
410 points_build_3x3_grid(scene, snap_data, strip);
411 }
412
413 for (Strip *strip : snap_targets) {
414 points_build_3x3_grid(scene, snap_data, strip);
415 }
416}
417
419
420/* -------------------------------------------------------------------- */
423
425{
426 const int snap_distance = seq::tool_settings_snap_distance_get(t->scene);
427 const View2D *v2d = &t->region->v2d;
428 return UI_view2d_region_to_view_x(v2d, snap_distance) - UI_view2d_region_to_view_x(v2d, 0);
429}
430
435
437
438/* -------------------------------------------------------------------- */
441
442static void snap_data_build_timeline(const TransInfo *t, TransSeqSnapData *snap_data)
443{
444 Scene *scene = t->scene;
445 short snap_mode = t->tsnap.mode;
446
447 Map retiming_selection = seq::retiming_selection_get(seq::editing_get(scene));
448 VectorSet<Strip *> snap_sources = query_snap_sources_timeline(scene, retiming_selection);
449 VectorSet<Strip *> snap_targets = query_snap_targets_timeline(scene, snap_sources, true);
450
451 /* Build arrays of snap points. */
453 points_build_sources_timeline_strips(scene, snap_data, snap_sources);
454 }
455 else { /* &TransConvertType_SequencerRetiming */
456 points_build_sources_timeline_retiming(scene, snap_data, retiming_selection);
457 }
458 points_build_targets_timeline(scene, snap_mode, snap_data, snap_targets);
459}
460
461static void snap_data_build_preview(const TransInfo *t, TransSeqSnapData *snap_data)
462{
463 Scene *scene = t->scene;
464 short snap_mode = t->tsnap.mode;
465 View2D *v2d = &t->region->v2d;
466 SpaceSeq *sseq = static_cast<SpaceSeq *>(t->area->spacedata.first);
467
469 VectorSet<Strip *> snap_targets;
470
471 snap_targets = query_snap_targets_preview(t);
472
473 /* Build arrays of snap points. */
475 if (t->flag & T_ORIGIN) {
476 points_build_sources_preview_origin(scene, snap_data, snap_sources);
477 points_build_targets_preview_origin(scene, snap_data, snap_sources, snap_targets);
478 }
479 else {
480 points_build_sources_preview_image(scene, snap_data, snap_sources);
481 points_build_targets_preview_image(scene, v2d, snap_mode, snap_data, snap_targets);
482 }
483 }
485 float2 cursor_view = float2(sseq->cursor) * float2(t->aspect);
486 snap_data->source_snap_points.append(cursor_view);
487 points_build_targets_preview_image(scene, v2d, snap_mode, snap_data, snap_targets);
488 }
489}
490
492{
493 TransSeqSnapData *snap_data = MEM_new<TransSeqSnapData>(__func__);
494
496 snap_data_build_timeline(t, snap_data);
497 }
498 else {
499 snap_data_build_preview(t, snap_data);
500 }
501
502 if (snap_data->source_snap_points.is_empty() || snap_data->target_snap_points.is_empty()) {
503 MEM_delete(snap_data);
504 return nullptr;
505 }
506
507 return snap_data;
508}
509
511{
512 MEM_delete(data);
513}
514
516
517/* -------------------------------------------------------------------- */
520
521static bool snap_calc_timeline(TransInfo *t, const TransSeqSnapData *snap_data)
522{
523 /* Prevent snapping when constrained to Y axis. */
524 if (t->con.mode & CON_APPLY && t->con.mode & CON_AXIS1) {
525 return false;
526 }
527
528 int best_dist = MAXFRAME, best_target_frame = 0, best_source_frame = 0;
529
530 for (const float *snap_source_point : snap_data->source_snap_points) {
531 for (const float *snap_target_point : snap_data->target_snap_points) {
532 int snap_source_frame = snap_source_point[0];
533 int snap_target_frame = snap_target_point[0];
534 int dist = abs(snap_target_frame - (snap_source_frame + round_fl_to_int(t->values[0])));
535 if (dist > best_dist) {
536 continue;
537 }
538
539 best_dist = dist;
540 best_target_frame = snap_target_frame;
541 best_source_frame = snap_source_frame;
542 }
543 }
544
545 if (best_dist > seq_snap_threshold_get_frame_distance(t)) {
546 return false;
547 }
548
549 float2 best_offset(float(best_target_frame - best_source_frame), 0.0f);
550 if (transform_convert_sequencer_clamp(t, best_offset)) {
551 return false;
552 }
553
554 t->tsnap.snap_target[0] = best_target_frame;
555 t->tsnap.snap_source[0] = best_source_frame;
556 return true;
557}
558
559static bool snap_calc_preview_origin(TransInfo *t, const TransSeqSnapData *snap_data)
560{
561 /* Store best snap candidates in x and y directions separately. */
562 float best_dist(std::numeric_limits<float>::max());
563 float2 best_target_point(0.0f);
564 float2 best_source_point(0.0f);
565
566 for (const float2 snap_source_point : snap_data->source_snap_points) {
567 for (const float2 snap_target_point : snap_data->target_snap_points) {
568 /* First update snaps in x direction, then y direction. */
569 const float2 transformed_point(snap_source_point.x + t->values[0],
570 snap_source_point.y + t->values[1]);
571 const float dist = blender::math::distance(snap_target_point, transformed_point);
572 if (dist > best_dist) {
573 continue;
574 }
575
576 best_dist = dist;
577 best_target_point = snap_target_point;
578 best_source_point = snap_source_point;
579 }
580 }
581
582 if (best_dist <= seq_snap_threshold_get_view_distance(t)) {
583 copy_v2_v2(t->tsnap.snap_target, best_target_point);
584 copy_v2_v2(t->tsnap.snap_source, best_source_point);
586 return true;
587 }
588 return false;
589}
590
591static bool snap_calc_preview_image(TransInfo *t, const TransSeqSnapData *snap_data)
592{
593 /* Store best snap candidates in x and y directions separately. */
594 float2 best_dist(std::numeric_limits<float>::max());
595 float2 best_target_point(0.0f);
596 float2 best_source_point(0.0f);
597
598 for (const float2 snap_source_point : snap_data->source_snap_points) {
599 for (const float2 snap_target_point : snap_data->target_snap_points) {
600 /* First update snaps in x direction, then y direction. */
601 for (int i = 0; i < 2; i++) {
602 int dist = abs(snap_target_point[i] - (snap_source_point[i] + t->values[i]));
603 if (dist > best_dist[i]) {
604 continue;
605 }
606
607 best_dist[i] = dist;
608 best_target_point[i] = snap_target_point[i];
609 best_source_point[i] = snap_source_point[i];
610 }
611 }
612 }
613
616
617 if (best_dist[0] <= thr) {
618 t->tsnap.snap_target[0] = best_target_point[0];
619 t->tsnap.snap_source[0] = best_source_point[0];
621 }
622
623 if (best_dist[1] <= thr) {
624 t->tsnap.snap_target[1] = best_target_point[1];
625 t->tsnap.snap_source[1] = best_source_point[1];
627 }
628
629 return (best_dist[0] <= thr || best_dist[1] <= thr);
630}
631
633{
634 const TransSeqSnapData *snap_data = t->tsnap.seq_context;
635 if (snap_data == nullptr) {
636 return false;
637 }
638
640 return snap_calc_timeline(t, snap_data);
641 }
642 if (t->flag & T_ORIGIN) {
643 return snap_calc_preview_origin(t, snap_data);
644 }
645 return snap_calc_preview_image(t, snap_data);
646}
647
649{
650 *vec = t->tsnap.snap_target[0] - t->tsnap.snap_source[0];
651}
652
654{
655 /* Apply snap along x and y axes independently. */
656 if (t->tsnap.direction & DIR_GLOBAL_X) {
657 vec[0] = t->tsnap.snap_target[0] - t->tsnap.snap_source[0];
658 }
659
660 if (t->tsnap.direction & DIR_GLOBAL_Y) {
661 vec[1] = t->tsnap.snap_target[1] - t->tsnap.snap_source[1];
662 }
663}
664
665static int snap_sequencer_to_closest_strip_ex(TransInfo *t, const int frame_1, const int frame_2)
666{
667 Scene *scene = t->scene;
668 TransSeqSnapData *snap_data = MEM_new<TransSeqSnapData>(__func__);
669
670 VectorSet<Strip *> empty_col;
671 VectorSet<Strip *> snap_targets = query_snap_targets_timeline(scene, empty_col, false);
672
673 BLI_assert(frame_1 <= frame_2);
674
675 snap_data->source_snap_points[0][0] = frame_1;
676 snap_data->source_snap_points[1][0] = frame_2;
677
678 short snap_mode = t->tsnap.mode;
679
680 /* Build arrays of snap target frames. */
681 points_build_targets_timeline(scene, snap_mode, snap_data, snap_targets);
682
683 t->tsnap.seq_context = snap_data;
684 bool snap_success = snap_sequencer_calc(t);
685 snap_sequencer_data_free(snap_data);
686 t->tsnap.seq_context = nullptr;
687
688 float snap_offset = 0;
689 if (snap_success) {
691 snap_sequencer_apply_seqslide(t, &snap_offset);
692 }
693 else {
695 }
696
697 return snap_offset;
698}
699
701 ARegion *region,
702 const int frame_1,
703 const int frame_2,
704 int *r_snap_distance,
705 float *r_snap_frame)
706{
707 TransInfo t = {nullptr};
708 t.scene = scene;
709 t.region = region;
710 t.values[0] = 0;
712
714 *r_snap_distance = snap_sequencer_to_closest_strip_ex(&t, frame_1, frame_2);
715 *r_snap_frame = t.tsnap.snap_target[0];
716 return validSnap(&t);
717}
718
719void sequencer_snap_point(ARegion *region, const float snap_point)
720{
721 /* Reuse the snapping drawing code from the transform system. */
722 TransInfo t = {nullptr};
726 t.tsnap.flag = SCE_SNAP;
728 t.tsnap.snap_target[0] = snap_point;
729 t.region = region;
730
731 drawSnapping(&t);
732}
733
735
736} // namespace blender::ed::transform
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
MINLINE int round_fl_to_int(float a)
MINLINE void copy_v2_v2(float r[2], const float a[2])
#define CLAMP(a, b, c)
#define ELEM(...)
@ SEQ_SNAP_IGNORE_SOUND
@ SEQ_SNAP_IGNORE_MUTED
#define PSFRA
@ SCE_SNAP
@ SEQ_SNAP_TO_MARKERS
@ SEQ_SNAP_TO_FRAME_RANGE
@ SEQ_SNAP_TO_PREVIEW_CENTER
@ SEQ_SNAP_TO_STRIPS_PREVIEW
@ SEQ_SNAP_TO_PREVIEW_BORDERS
@ SEQ_SNAP_TO_STRIP_HOLD
@ SEQ_SNAP_TO_RETIMING
@ SEQ_SNAP_TO_CURRENT_FRAME
#define PEFRA
#define MAXFRAME
@ STRIP_TYPE_SOUND_RAM
@ SEQ_RIGHTSEL
@ SEQ_LEFTSEL
@ SPACE_SEQ
Read Guarded memory(de)allocation.
float UI_view2d_region_to_view_x(const View2D *v2d, float x)
Definition view2d.cc:1657
BMesh const char void * data
BMesh * bm
ValueIterator values() const &
Definition BLI_map.hh:884
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:295
ItemIterator items() const &
Definition BLI_map.hh:902
constexpr int64_t size() const
Definition BLI_span.hh:252
bool add(const Key &key)
bool contains(const Key &key) const
int64_t remove_if(Predicate &&predicate)
#define SELECT
#define abs
static int left
static void points_build_targets_timeline(const Scene *scene, const short snap_mode, TransSeqSnapData *snap_data, const Span< Strip * > strip_targets)
static bool snap_calc_preview_image(TransInfo *t, const TransSeqSnapData *snap_data)
static void points_build_sources_preview_image(const Scene *scene, TransSeqSnapData *snap_data, const Span< Strip * > snap_sources)
void sequencer_snap_point(ARegion *region, float snap_point)
static void points_build_3x3_grid(const Scene *scene, TransSeqSnapData *snap_data, Strip *strip)
TransConvertTypeInfo TransConvertType_Sequencer
static void snap_data_build_timeline(const TransInfo *t, TransSeqSnapData *snap_data)
static void points_build_sources_preview_origin(const Scene *scene, TransSeqSnapData *snap_data, const Span< Strip * > snap_sources)
static float seq_snap_threshold_get_view_distance(const TransInfo *t)
static Map< SeqRetimingKey *, Strip * > visible_retiming_keys_get(const Scene *scene, Span< Strip * > snap_strip_targets)
bool validSnap(const TransInfo *t)
static int seq_snap_threshold_get_frame_distance(const TransInfo *t)
void snap_sequencer_apply_seqslide(TransInfo *t, float *vec)
static void query_strip_effects_fn(const Scene *scene, Strip *strip_reference, ListBase *seqbase, VectorSet< Strip * > &strips)
static VectorSet< Strip * > query_snap_targets_timeline(Scene *scene, const Span< Strip * > snap_sources, const bool exclude_selected)
void snap_sequencer_image_apply_translate(TransInfo *t, float vec[2])
static void snap_data_build_preview(const TransInfo *t, TransSeqSnapData *snap_data)
static void points_build_sources_timeline_retiming(const Scene *scene, TransSeqSnapData *snap_data, const Map< SeqRetimingKey *, Strip * > &retiming_selection)
bool transform_convert_sequencer_clamp(const TransInfo *t, float r_val[2])
static VectorSet< Strip * > query_snap_sources_timeline(const Scene *scene, Map< SeqRetimingKey *, Strip * > &retiming_selection)
void drawSnapping(TransInfo *t)
TransSeqSnapData * snap_sequencer_data_alloc(const TransInfo *t)
static void points_build_targets_preview_origin(const Scene *scene, TransSeqSnapData *snap_data, const Span< Strip * > snap_sources, const Span< Strip * > snap_targets)
static void points_build_sources_timeline_strips(const Scene *scene, TransSeqSnapData *snap_data, const Span< Strip * > snap_sources)
bool snap_sequencer_to_closest_strip_calc(Scene *scene, ARegion *region, int frame_1, int frame_2, int *r_snap_distance, float *r_snap_frame)
static VectorSet< Strip * > query_snap_sources_preview(const Scene *scene)
static int snap_sequencer_to_closest_strip_ex(TransInfo *t, const int frame_1, const int frame_2)
static void points_build_targets_preview_general(const View2D *v2d, const short snap_mode, TransSeqSnapData *snap_data)
void snap_sequencer_data_free(TransSeqSnapData *data)
static VectorSet< Strip * > query_snap_targets_preview(const TransInfo *t)
static int cmp_fn(const void *a, const void *b)
TransConvertTypeInfo TransConvertType_CursorSequencer
static bool snap_calc_timeline(TransInfo *t, const TransSeqSnapData *snap_data)
static void points_build_targets_preview_image(const Scene *scene, const View2D *v2d, const short snap_mode, TransSeqSnapData *snap_data, const Span< Strip * > snap_targets)
static bool snap_calc_preview_origin(TransInfo *t, const TransSeqSnapData *snap_data)
T distance(const T &a, const T &b)
T interpolate(const T &a, const T &b, const FactorT &t)
bool render_is_muted(const ListBase *channels, const Strip *strip)
Definition render.cc:2110
int time_right_handle_frame_get(const Scene *scene, const Strip *strip)
Array< float2 > image_transform_final_quad_get(const Scene *scene, const Strip *strip)
ListBase * channels_displayed_get(const Editing *ed)
Definition channels.cc:28
float time_content_end_frame_get(const Scene *scene, const Strip *strip)
VectorSet< Strip * > query_selected_strips(ListBase *seqbase)
Definition iterator.cc:152
blender::Map< SeqRetimingKey *, Strip * > retiming_selection_get(const Editing *ed)
int retiming_key_timeline_frame_get(const Scene *scene, const Strip *strip, const SeqRetimingKey *key)
Editing * editing_get(const Scene *scene)
Definition sequencer.cc:286
MutableSpan< SeqRetimingKey > retiming_keys_get(const Strip *strip)
int time_left_handle_frame_get(const Scene *, const Strip *strip)
float time_start_frame_get(const Strip *strip)
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 time_strip_intersects_frame(const Scene *scene, const Strip *strip, const int timeline_frame)
float2 image_transform_origin_offset_pixelspace_get(const Scene *scene, const Strip *strip)
short tool_settings_snap_flag_get(Scene *scene)
Definition sequencer.cc:403
int tool_settings_snap_distance_get(Scene *scene)
Definition sequencer.cc:409
bool relation_is_effect_of_strip(const Strip *effect, const Strip *input)
VectorSet< Strip * > query_rendered_strips(const Scene *scene, ListBase *channels, ListBase *seqbase, const int timeline_frame, const int displayed_channel)
Definition iterator.cc:228
ListBase * active_seqbase_get(const Editing *ed)
Definition sequencer.cc:433
short tool_settings_snap_mode_get(Scene *scene)
Definition sequencer.cc:397
int effect_get_num_inputs(int strip_type)
Definition effects.cc:327
VecBase< float, 2 > float2
void * first
struct RenderData r
ListBase markers
ListBase spacedata
float cursor[2]
TransConvertTypeInfo * data_type
Definition transform.hh:810
float xmax
float xmin
float ymax
float ymin
i
Definition text_draw.cc:230
conversion and adaptation of different datablocks to a common struct.