Blender V4.3
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
9#include <cstdlib>
10
11#include "MEM_guardedalloc.h"
12
13#include "DNA_sequence_types.h"
14
15#include "ED_screen.hh"
16#include "ED_transform.hh"
17
18#include "UI_view2d.hh"
19
20#include "SEQ_channels.hh"
21#include "SEQ_effects.hh"
22#include "SEQ_iterator.hh"
23#include "SEQ_relations.hh"
24#include "SEQ_render.hh"
25#include "SEQ_sequencer.hh"
26#include "SEQ_time.hh"
27#include "SEQ_transform.hh"
28
29#include "transform.hh"
30#include "transform_convert.hh"
31#include "transform_snap.hh"
32
36
37#ifdef WITH_CXX_GUARDEDALLOC
38 MEM_CXX_CLASS_ALLOC_FUNCS("TransSeqSnapData")
39#endif
40};
41
42/* -------------------------------------------------------------------- */
47{
49
51 snap_sources = SEQ_query_selected_strips(seqbase);
52
53 return snap_sources;
54}
55
57{
59
60 Editing *ed = SEQ_editing_get(scene);
62
63 snap_sources = SEQ_query_rendered_strips(scene, channels, ed->seqbasep, scene->r.cfra, 0);
64 snap_sources.remove_if([&](Sequence *seq) { return (seq->flag & SELECT) == 0; });
65
66 return snap_sources;
67}
68
70{
71 return snap_sources.size() * 2;
72}
73
75{
76 /* Source points are four corners and the center of an image quad. */
77 return snap_sources.size() * 5;
78}
79
80static int cmp_fn(const void *a, const void *b)
81{
82 return round_fl_to_int((*(blender::float2 *)a)[0] - (*(blender::float2 *)b)[0]);
83}
84
86 TransSeqSnapData *snap_data,
87 const blender::Span<Sequence *> snap_sources)
88{
89
90 const size_t point_count_source = seq_get_snap_source_points_count_timeline(snap_sources);
91 if (point_count_source == 0) {
92 return false;
93 }
94
95 snap_data->source_snap_points.reinitialize(point_count_source);
96 int i = 0;
97 for (Sequence *seq : snap_sources) {
98 int left = 0, right = 0;
99 if (seq->flag & SEQ_LEFTSEL && !(seq->flag & SEQ_RIGHTSEL)) {
100 left = right = SEQ_time_left_handle_frame_get(scene, seq);
101 }
102 else if (seq->flag & SEQ_RIGHTSEL && !(seq->flag & SEQ_LEFTSEL)) {
103 left = right = SEQ_time_right_handle_frame_get(scene, seq);
104 }
105 else {
106 left = SEQ_time_left_handle_frame_get(scene, seq);
107 right = SEQ_time_right_handle_frame_get(scene, seq);
108 }
109
110 /* Set only the x-positions when snapping in the timeline. */
111 snap_data->source_snap_points[i][0] = left;
112 snap_data->source_snap_points[i + 1][0] = right;
113 i += 2;
114 BLI_assert(i <= snap_data->source_snap_points.size());
115 }
116
117 qsort(snap_data->source_snap_points.data(),
118 snap_data->source_snap_points.size(),
119 sizeof(blender::float2),
120 cmp_fn);
121
122 return true;
123}
124
126 TransSeqSnapData *snap_data,
127 const blender::Span<Sequence *> snap_sources)
128{
129
130 const size_t point_count_source = seq_get_snap_source_points_count_preview(snap_sources);
131 if (point_count_source == 0) {
132 return false;
133 }
134
135 snap_data->source_snap_points.reinitialize(point_count_source);
136 int i = 0;
137 for (Sequence *seq : snap_sources) {
138 float seq_image_quad[4][2];
139 SEQ_image_transform_final_quad_get(scene, seq, seq_image_quad);
140
141 for (int j = 0; j < 4; j++) {
142 snap_data->source_snap_points[i][0] = seq_image_quad[j][0];
143 snap_data->source_snap_points[i][1] = seq_image_quad[j][1];
144 i++;
145 }
146
147 /* Add origins last */
148 float image_origin[2];
149 SEQ_image_transform_origin_offset_pixelspace_get(scene, seq, image_origin);
150 snap_data->source_snap_points[i][0] = image_origin[0];
151 snap_data->source_snap_points[i][1] = image_origin[1];
152 i++;
153
154 BLI_assert(i <= snap_data->source_snap_points.size());
155 }
156
157 return true;
158}
159
162/* -------------------------------------------------------------------- */
166/* Add effect strips directly or indirectly connected to `seq_reference` to `collection`. */
167static void query_strip_effects_fn(const Scene *scene,
168 Sequence *seq_reference,
169 ListBase *seqbase,
171{
172 if (strips.contains(seq_reference)) {
173 return; /* Strip is already in set, so all effects connected to it are as well. */
174 }
175 strips.add(seq_reference);
176
177 /* Find all strips connected to `seq_reference`. */
178 LISTBASE_FOREACH (Sequence *, seq_test, seqbase) {
179 if (SEQ_relation_is_effect_of_strip(seq_test, seq_reference)) {
180 query_strip_effects_fn(scene, seq_test, seqbase, strips);
181 }
182 }
183}
184
186 Scene *scene, const blender::Span<Sequence *> snap_sources, const bool exclude_selected)
187{
188 Editing *ed = SEQ_editing_get(scene);
189 ListBase *seqbase = SEQ_active_seqbase_get(ed);
190 ListBase *channels = SEQ_channels_displayed_get(ed);
191 const short snap_flag = SEQ_tool_settings_snap_flag_get(scene);
192
193 /* Effects will always change position with strip to which they are connected and they don't
194 * have to be selected. Remove such strips from `snap_targets` collection. */
195 blender::VectorSet effects_of_snap_sources = snap_sources;
196 SEQ_iterator_set_expand(scene, seqbase, effects_of_snap_sources, query_strip_effects_fn);
197 effects_of_snap_sources.remove_if(
198 [&](Sequence *seq) { return SEQ_effect_get_num_inputs(seq->type) == 0; });
199
201 LISTBASE_FOREACH (Sequence *, seq, seqbase) {
202 if (exclude_selected && seq->flag & SELECT) {
203 continue; /* Selected are being transformed if there is no drag and drop. */
204 }
205 if (SEQ_render_is_muted(channels, seq) && (snap_flag & SEQ_SNAP_IGNORE_MUTED)) {
206 continue;
207 }
208 if (seq->type == SEQ_TYPE_SOUND_RAM && (snap_flag & SEQ_SNAP_IGNORE_SOUND)) {
209 continue;
210 }
211 if (effects_of_snap_sources.contains(seq)) {
212 continue;
213 }
214
215 snap_targets.add(seq);
216 }
217
218 return snap_targets;
219}
220
222 const short snap_mode)
223{
225
226 /* We don't need to calculate strip snap targets if the option is unselected. */
227 if ((snap_mode & SEQ_SNAP_TO_STRIPS_PREVIEW) == 0) {
228 return snap_targets;
229 }
230
231 Editing *ed = SEQ_editing_get(scene);
232 ListBase *channels = SEQ_channels_displayed_get(ed);
233
234 snap_targets = SEQ_query_rendered_strips(scene, channels, ed->seqbasep, scene->r.cfra, 0);
235 snap_targets.remove_if([&](Sequence *seq) { return (seq->flag & SELECT) == 1; });
236
237 return snap_targets;
238}
239
241 const short snap_mode,
242 const blender::Span<Sequence *> snap_targets)
243{
244 int count = 0;
245
246 if (snap_mode & SEQ_SNAP_TO_STRIPS) {
247 count += 2; /* Strip start and end are always used. */
248 }
249
250 if (snap_mode & SEQ_SNAP_TO_STRIP_HOLD) {
251 count += 2;
252 }
253
254 count *= snap_targets.size();
255
256 if (snap_mode & SEQ_SNAP_TO_CURRENT_FRAME) {
257 count++;
258 }
259
260 if (snap_mode & SEQ_SNAP_TO_MARKERS) {
261 count += BLI_listbase_count(&scene->markers);
262 }
263
264 return count;
265}
266
267static int seq_get_snap_target_points_count_preview(const short snap_mode,
268 const blender::Span<Sequence *> snap_targets)
269{
270 int count = 0;
271
272 if (snap_mode & SEQ_SNAP_TO_PREVIEW_BORDERS) {
273 /* Opposite corners of the view have enough information to snap to all four corners. */
274 count += 2;
275 }
276
277 if (snap_mode & SEQ_SNAP_TO_PREVIEW_CENTER) {
278 count++;
279 }
280
281 if (snap_mode & SEQ_SNAP_TO_STRIPS_PREVIEW) {
282 /* Snap to other strips' corners and center. */
283 count += snap_targets.size() * 5;
284 }
285
286 return count;
287}
288
290 const short snap_mode,
291 TransSeqSnapData *snap_data,
292 const blender::Span<Sequence *> snap_targets)
293{
294
295 const size_t point_count_target = seq_get_snap_target_points_count_timeline(
296 scene, snap_mode, snap_targets);
297 if (point_count_target == 0) {
298 return false;
299 }
300
301 snap_data->target_snap_points.reinitialize(point_count_target);
302 int i = 0;
303
304 if (snap_mode & SEQ_SNAP_TO_CURRENT_FRAME) {
305 snap_data->target_snap_points[i][0] = scene->r.cfra;
306 i++;
307 }
308
309 if (snap_mode & SEQ_SNAP_TO_MARKERS) {
310 LISTBASE_FOREACH (TimeMarker *, marker, &scene->markers) {
311 snap_data->target_snap_points[i][0] = marker->frame;
312 i++;
313 }
314 }
315
316 for (Sequence *seq : snap_targets) {
317 snap_data->target_snap_points[i][0] = SEQ_time_left_handle_frame_get(scene, seq);
318 snap_data->target_snap_points[i + 1][0] = SEQ_time_right_handle_frame_get(scene, seq);
319 i += 2;
320
321 if (snap_mode & SEQ_SNAP_TO_STRIP_HOLD) {
322 int content_start = SEQ_time_start_frame_get(seq);
323 int content_end = SEQ_time_content_end_frame_get(scene, seq);
324
325 /* Effects and single image strips produce incorrect content length. Skip these strips. */
326 if ((seq->type & SEQ_TYPE_EFFECT) != 0 || seq->len == 1) {
327 content_start = SEQ_time_left_handle_frame_get(scene, seq);
328 content_end = SEQ_time_right_handle_frame_get(scene, seq);
329 }
330
331 CLAMP(content_start,
334 CLAMP(content_end,
337
338 snap_data->target_snap_points[i][0] = content_start;
339 snap_data->target_snap_points[i + 1][0] = content_end;
340 i += 2;
341 }
342 }
343 BLI_assert(i <= snap_data->target_snap_points.size());
344 qsort(snap_data->target_snap_points.data(),
345 snap_data->target_snap_points.size(),
346 sizeof(blender::float2),
347 cmp_fn);
348 return true;
349}
350
352 const View2D *v2d,
353 const short snap_mode,
354 TransSeqSnapData *snap_data,
355 const blender::Span<Sequence *> snap_targets)
356{
357
358 const size_t point_count_target = seq_get_snap_target_points_count_preview(snap_mode,
359 snap_targets);
360 if (point_count_target == 0) {
361 return false;
362 }
363
364 snap_data->target_snap_points.reinitialize(point_count_target);
365 int i = 0;
366
367 if (snap_mode & SEQ_SNAP_TO_PREVIEW_BORDERS) {
368 snap_data->target_snap_points[i][0] = v2d->tot.xmin;
369 snap_data->target_snap_points[i][1] = v2d->tot.ymin;
370
371 snap_data->target_snap_points[i + 1][0] = v2d->tot.xmax;
372 snap_data->target_snap_points[i + 1][1] = v2d->tot.ymax;
373
374 i += 2;
375 }
376
377 if (snap_mode & SEQ_SNAP_TO_PREVIEW_CENTER) {
378 snap_data->target_snap_points[i][0] = 0;
379 snap_data->target_snap_points[i][1] = 0;
380
381 i++;
382 }
383
384 if (snap_mode & SEQ_SNAP_TO_STRIPS_PREVIEW) {
385 for (Sequence *seq : snap_targets) {
386 float seq_image_quad[4][2];
387 SEQ_image_transform_final_quad_get(scene, seq, seq_image_quad);
388
389 for (int j = 0; j < 4; j++) {
390 snap_data->target_snap_points[i][0] = seq_image_quad[j][0];
391 snap_data->target_snap_points[i][1] = seq_image_quad[j][1];
392 i++;
393 }
394
395 float image_origin[2];
396 SEQ_image_transform_origin_offset_pixelspace_get(scene, seq, image_origin);
397 snap_data->target_snap_points[i][0] = image_origin[0];
398 snap_data->target_snap_points[i][1] = image_origin[1];
399
400 i++;
401 }
402 }
403 BLI_assert(i <= snap_data->target_snap_points.size());
404
405 return true;
406}
407
410/* -------------------------------------------------------------------- */
415{
416 const int snap_distance = SEQ_tool_settings_snap_distance_get(t->scene);
417 const View2D *v2d = &t->region->v2d;
418 return UI_view2d_region_to_view_x(v2d, snap_distance) - UI_view2d_region_to_view_x(v2d, 0);
419}
420
425
429{
430 TransSeqSnapData *snap_data = MEM_new<TransSeqSnapData>(__func__);
431
432 Scene *scene = t->scene;
433 short snap_mode = t->tsnap.mode;
434
437 scene, snap_sources, true);
438
439 /* Build arrays of snap points. */
440 if (!seq_snap_source_points_build_timeline(scene, snap_data, snap_sources) ||
441 !seq_snap_target_points_build_timeline(scene, snap_mode, snap_data, snap_targets))
442 {
443 MEM_delete(snap_data);
444 return nullptr;
445 }
446
447 return snap_data;
448}
449
451{
452 TransSeqSnapData *snap_data = MEM_new<TransSeqSnapData>(__func__);
453
454 Scene *scene = t->scene;
455 short snap_mode = t->tsnap.mode;
456 View2D *v2d = &t->region->v2d;
457
459 blender::VectorSet<Sequence *> snap_targets = query_snap_targets_preview(scene, snap_mode);
460
461 /* Build arrays of snap points. */
462 if (!seq_snap_source_points_build_preview(scene, snap_data, snap_sources) ||
463 !seq_snap_target_points_build_preview(scene, v2d, snap_mode, snap_data, snap_targets))
464 {
465 MEM_delete(snap_data);
466 return nullptr;
467 }
468
469 return snap_data;
470}
471
485
487{
488 MEM_delete(data);
489}
490
492{
493 /* Prevent snapping when constrained to Y axis. */
494 if (t->con.mode & CON_APPLY && t->con.mode & CON_AXIS1) {
495 return false;
496 }
497
498 int best_dist = MAXFRAME, best_target_frame = 0, best_source_frame = 0;
499
500 for (const float *snap_source_point : snap_data->source_snap_points) {
501 for (const float *snap_target_point : snap_data->target_snap_points) {
502 int snap_source_frame = snap_source_point[0];
503 int snap_target_frame = snap_target_point[0];
504 int dist = abs(snap_target_frame - (snap_source_frame + round_fl_to_int(t->values[0])));
505 if (dist > best_dist) {
506 continue;
507 }
508
509 best_dist = dist;
510 best_target_frame = snap_target_frame;
511 best_source_frame = snap_source_frame;
512 }
513 }
514
515 if (best_dist > seq_snap_threshold_get_frame_distance(t)) {
516 return false;
517 }
518
519 t->tsnap.snap_target[0] = best_target_frame;
520 t->tsnap.snap_source[0] = best_source_frame;
521 return true;
522}
523
525{
526 /* Store best snap candidates in x and y directions separately. */
527 blender::float2 best_dist(std::numeric_limits<float>::max());
528 blender::float2 best_target_point(0.0f);
529 blender::float2 best_source_point(0.0f);
530
531 for (const float *snap_source_point : snap_data->source_snap_points) {
532 for (const float *snap_target_point : snap_data->target_snap_points) {
533 /* First update snaps in x direction, then y direction. */
534 for (int i = 0; i < 2; i++) {
535 int dist = abs(snap_target_point[i] - (snap_source_point[i] + t->values[i]));
536 if (dist > best_dist[i]) {
537 continue;
538 }
539
540 best_dist[i] = dist;
541 best_target_point[i] = snap_target_point[i];
542 best_source_point[i] = snap_source_point[i];
543 }
544 }
545 }
546
549
550 if (best_dist[0] <= thr) {
551 t->tsnap.snap_target[0] = best_target_point[0];
552 t->tsnap.snap_source[0] = best_source_point[0];
554 }
555
556 if (best_dist[1] <= thr) {
557 t->tsnap.snap_target[1] = best_target_point[1];
558 t->tsnap.snap_source[1] = best_source_point[1];
560 }
561
562 return (best_dist[0] <= thr || best_dist[1] <= thr);
563}
564
566{
567 const TransSeqSnapData *snap_data = t->tsnap.seq_context;
568 if (snap_data == nullptr) {
569 return false;
570 }
571
573 return transform_snap_sequencer_calc_timeline(t, snap_data);
574 }
575 else {
576 return transform_snap_sequencer_calc_preview(t, snap_data);
577 }
578}
579
581{
582 *vec = t->tsnap.snap_target[0] - t->tsnap.snap_source[0];
583}
584
586{
587 /* Apply snap along x and y axes independently. */
588 if (t->tsnap.direction & DIR_GLOBAL_X) {
589 vec[0] = t->tsnap.snap_target[0] - t->tsnap.snap_source[0];
590 }
591
592 if (t->tsnap.direction & DIR_GLOBAL_Y) {
593 vec[1] = t->tsnap.snap_target[1] - t->tsnap.snap_source[1];
594 }
595}
596
598 const int frame_1,
599 const int frame_2)
600{
601 Scene *scene = t->scene;
602 TransSeqSnapData *snap_data = MEM_new<TransSeqSnapData>(__func__);
603
606 scene, empty_col, false);
607
608 BLI_assert(frame_1 <= frame_2);
609 snap_data->source_snap_points.reinitialize(2);
610 snap_data->source_snap_points[0][0] = frame_1;
611 snap_data->source_snap_points[1][0] = frame_2;
612
613 short snap_mode = t->tsnap.mode;
614
615 /* Build arrays of snap target frames. */
616 seq_snap_target_points_build_timeline(scene, snap_mode, snap_data, snap_targets);
617
618 t->tsnap.seq_context = snap_data;
619 bool snap_success = transform_snap_sequencer_calc(t);
621 t->tsnap.seq_context = nullptr;
622
623 float snap_offset = 0;
624 if (snap_success) {
627 }
628 else {
630 }
631
632 return snap_offset;
633}
634
636 ARegion *region,
637 const int frame_1,
638 const int frame_2,
639 int *r_snap_distance,
640 float *r_snap_frame)
641{
642 TransInfo t = {nullptr};
643 t.scene = scene;
644 t.region = region;
645 t.values[0] = 0;
647
649 *r_snap_distance = transform_snap_sequencer_to_closest_strip_ex(&t, frame_1, frame_2);
650 *r_snap_frame = t.tsnap.snap_target[0];
651 return validSnap(&t);
652}
653
654void ED_draw_sequencer_snap_point(ARegion *region, const float snap_point)
655{
656 /* Reuse the snapping drawing code from the transform system. */
657 TransInfo t = {nullptr};
661 t.tsnap.flag = SCE_SNAP;
663 t.tsnap.snap_target[0] = snap_point;
664 t.region = region;
665
666 drawSnapping(&t);
667}
#define BLI_assert(a)
Definition BLI_assert.h:50
#define LISTBASE_FOREACH(type, var, list)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int round_fl_to_int(float a)
#define CLAMP(a, b, c)
@ SEQ_SNAP_TO_STRIPS
@ SEQ_SNAP_TO_MARKERS
@ SEQ_SNAP_TO_PREVIEW_CENTER
@ SEQ_SNAP_TO_STRIPS_PREVIEW
@ SEQ_SNAP_TO_PREVIEW_BORDERS
@ SEQ_SNAP_TO_STRIP_HOLD
@ SEQ_SNAP_TO_CURRENT_FRAME
@ SEQ_SNAP_IGNORE_SOUND
@ SEQ_SNAP_IGNORE_MUTED
@ SCE_SNAP
#define MAXFRAME
@ SEQ_TYPE_SOUND_RAM
@ SEQ_TYPE_EFFECT
@ SEQ_RIGHTSEL
@ SEQ_LEFTSEL
@ SPACE_SEQ
@ TFM_SEQ_SLIDE
Read Guarded memory(de)allocation.
float UI_view2d_region_to_view_x(const View2D *v2d, float x)
Definition view2d.cc:1652
ListBase * SEQ_channels_displayed_get(Editing *ed)
Definition channels.cc:23
int64_t size() const
Definition BLI_array.hh:245
constexpr int64_t size() const
Definition BLI_span.hh:253
bool add(const Key &key)
bool contains(const Key &key) const
int64_t remove_if(Predicate &&predicate)
local_group_size(16, 16) .push_constant(Type b
#define SELECT
int SEQ_effect_get_num_inputs(int seq_type)
Definition effects.cc:3467
int count
VectorSet< Sequence * > SEQ_query_rendered_strips(const Scene *scene, ListBase *channels, ListBase *seqbase, const int timeline_frame, const int displayed_channel)
Definition iterator.cc:184
void SEQ_iterator_set_expand(const Scene *scene, ListBase *seqbase, VectorSet< Sequence * > &strips, void seq_query_func(const Scene *scene, Sequence *seq_reference, ListBase *seqbase, VectorSet< Sequence * > &strips))
Definition iterator.cc:61
VectorSet< Sequence * > SEQ_query_selected_strips(ListBase *seqbase)
Definition iterator.cc:106
static int left
bool SEQ_render_is_muted(const ListBase *channels, const Sequence *seq)
Definition render.cc:2154
ListBase * SEQ_active_seqbase_get(const Editing *ed)
Definition sequencer.cc:416
short SEQ_tool_settings_snap_mode_get(Scene *scene)
Definition sequencer.cc:380
int SEQ_tool_settings_snap_distance_get(Scene *scene)
Definition sequencer.cc:392
short SEQ_tool_settings_snap_flag_get(Scene *scene)
Definition sequencer.cc:386
Editing * SEQ_editing_get(const Scene *scene)
Definition sequencer.cc:262
bool SEQ_relation_is_effect_of_strip(const Sequence *effect, const Sequence *input)
int SEQ_time_left_handle_frame_get(const Scene *, const Sequence *seq)
float SEQ_time_content_end_frame_get(const Scene *scene, const Sequence *seq)
float SEQ_time_start_frame_get(const Sequence *seq)
int SEQ_time_right_handle_frame_get(const Scene *scene, const Sequence *seq)
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])
ListBase * seqbasep
eTConstraint mode
Definition transform.hh:351
eTfmMode mode
Definition transform.hh:517
char spacetype
Definition transform.hh:582
float values[4]
Definition transform.hh:624
TransSnap tsnap
Definition transform.hh:537
eTModifier modifiers
Definition transform.hh:525
Scene * scene
Definition transform.hh:654
ARegion * region
Definition transform.hh:652
TransCon con
Definition transform.hh:534
TransConvertTypeInfo * data_type
Definition transform.hh:513
blender::Array< blender::float2 > target_snap_points
blender::Array< blender::float2 > source_snap_points
TransSeqSnapData * seq_context
Definition transform.hh:341
eSnapFlag flag
Definition transform.hh:310
eTSnap status
Definition transform.hh:318
float snap_target[3]
Definition transform.hh:327
float snap_source[3]
Definition transform.hh:325
eSnapMode mode
Definition transform.hh:312
eSnapDir direction
Definition transform.hh:323
float xmax
float xmin
float ymax
float ymin
@ SNAP_TARGET_FOUND
Definition transform.hh:177
@ SNAP_SOURCE_FOUND
Definition transform.hh:175
@ CON_APPLY
Definition transform.hh:193
@ CON_AXIS1
Definition transform.hh:196
@ MOD_SNAP
Definition transform.hh:163
@ DIR_GLOBAL_Y
Definition transform.hh:185
@ DIR_GLOBAL_X
Definition transform.hh:184
conversion and adaptation of different datablocks to a common struct.
TransConvertTypeInfo TransConvertType_Sequencer
TransConvertTypeInfo TransConvertType_SequencerRetiming
bool validSnap(const TransInfo *t)
void drawSnapping(TransInfo *t)
static blender::VectorSet< Sequence * > query_snap_sources_timeline(const Scene *scene)
void transform_snap_sequencer_image_apply_translate(TransInfo *t, float vec[2])
static int seq_get_snap_source_points_count_preview(const blender::Span< Sequence * > snap_sources)
void transform_snap_sequencer_apply_seqslide(TransInfo *t, float *vec)
static int seq_get_snap_target_points_count_preview(const short snap_mode, const blender::Span< Sequence * > snap_targets)
static int transform_snap_sequencer_to_closest_strip_ex(TransInfo *t, const int frame_1, const int frame_2)
static blender::VectorSet< Sequence * > query_snap_sources_preview(const Scene *scene)
static bool seq_snap_target_points_build_preview(const Scene *scene, const View2D *v2d, const short snap_mode, TransSeqSnapData *snap_data, const blender::Span< Sequence * > snap_targets)
static bool seq_snap_target_points_build_timeline(const Scene *scene, const short snap_mode, TransSeqSnapData *snap_data, const blender::Span< Sequence * > snap_targets)
void transform_snap_sequencer_data_free(TransSeqSnapData *data)
static bool seq_snap_source_points_build_preview(const Scene *scene, TransSeqSnapData *snap_data, const blender::Span< Sequence * > snap_sources)
static blender::VectorSet< Sequence * > query_snap_targets_timeline(Scene *scene, const blender::Span< Sequence * > snap_sources, const bool exclude_selected)
static bool transform_snap_sequencer_calc_preview(TransInfo *t, const TransSeqSnapData *snap_data)
static float seq_snap_threshold_get_view_distance(const TransInfo *t)
static int seq_get_snap_source_points_count_timeline(const blender::Span< Sequence * > snap_sources)
bool ED_transform_snap_sequencer_to_closest_strip_calc(Scene *scene, ARegion *region, const int frame_1, const int frame_2, int *r_snap_distance, float *r_snap_frame)
static TransSeqSnapData * transform_snap_sequencer_data_alloc_preview(const TransInfo *t)
static void query_strip_effects_fn(const Scene *scene, Sequence *seq_reference, ListBase *seqbase, blender::VectorSet< Sequence * > &strips)
static int seq_get_snap_target_points_count_timeline(const Scene *scene, const short snap_mode, const blender::Span< Sequence * > snap_targets)
static TransSeqSnapData * transform_snap_sequencer_data_alloc_timeline(const TransInfo *t)
void ED_draw_sequencer_snap_point(ARegion *region, const float snap_point)
TransSeqSnapData * transform_snap_sequencer_data_alloc(const TransInfo *t)
static bool seq_snap_source_points_build_timeline(const Scene *scene, TransSeqSnapData *snap_data, const blender::Span< Sequence * > snap_sources)
static int seq_snap_threshold_get_frame_distance(const TransInfo *t)
static bool transform_snap_sequencer_calc_timeline(TransInfo *t, const TransSeqSnapData *snap_data)
bool transform_snap_sequencer_calc(TransInfo *t)
static int cmp_fn(const void *a, const void *b)
static blender::VectorSet< Sequence * > query_snap_targets_preview(Scene *scene, const short snap_mode)
ccl_device_inline int abs(int x)
Definition util/math.h:120