Blender V5.0
sequencer_retiming_draw.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "BLI_string_utf8.h"
10
11#include "DNA_sequence_types.h"
12
13#include "BKE_context.hh"
14#include "BKE_fcurve.hh"
15
16#include "BLF_api.hh"
17
18#include "GPU_immediate.hh"
19#include "GPU_matrix.hh"
20#include "GPU_state.hh"
21#include "GPU_vertex_format.hh"
22
23#include "WM_api.hh"
24#include "WM_types.hh"
25
26#include "ED_keyframes_draw.hh"
28#include "ED_screen.hh"
29
30#include "UI_view2d.hh"
31
32#include "SEQ_retiming.hh"
33#include "SEQ_time.hh"
34
35/* Own include. */
36#include "sequencer_intern.hh"
38
39namespace blender::ed::vse {
40
41#define KEY_SIZE (10 * U.pixelsize)
42#define KEY_CENTER \
43 (UI_view2d_view_to_region_y(v2d, strip_y_rescale(strip, 0.0f)) + 4 + KEY_SIZE / 2)
44
50
51static float strip_y_rescale(const Strip *strip, const float y_value)
52{
53 const float y_range = STRIP_OFSTOP - STRIP_OFSBOTTOM;
54 return (y_value * y_range) + strip->channel + STRIP_OFSBOTTOM;
55}
56
57static float key_x_get(const Scene *scene, const Strip *strip, const SeqRetimingKey *key)
58{
59 return seq::retiming_key_timeline_frame_get(scene, strip, key);
60}
61
62static float pixels_to_view_width(const bContext *C, const float width)
63{
64 const View2D *v2d = UI_view2d_fromcontext(C);
65 float scale_x = UI_view2d_view_to_region_x(v2d, 1) - UI_view2d_view_to_region_x(v2d, 0.0f);
66 return width / scale_x;
67}
68
69static float pixels_to_view_height(const bContext *C, const float height)
70{
71 const View2D *v2d = UI_view2d_fromcontext(C);
72 float scale_y = UI_view2d_view_to_region_y(v2d, 1) - UI_view2d_view_to_region_y(v2d, 0.0f);
73 return height / scale_y;
74}
75
76static float strip_start_screenspace_get(const Scene *scene, const View2D *v2d, const Strip *strip)
77{
79}
80
81static float strip_end_screenspace_get(const Scene *scene, const View2D *v2d, const Strip *strip)
82{
84}
85
86static rctf strip_box_get(const Scene *scene, const View2D *v2d, const Strip *strip)
87{
88 rctf rect;
89 rect.xmin = strip_start_screenspace_get(scene, v2d, strip);
90 rect.xmax = strip_end_screenspace_get(scene, v2d, strip);
91 rect.ymin = UI_view2d_view_to_region_y(v2d, strip_y_rescale(strip, 0));
92 rect.ymax = UI_view2d_view_to_region_y(v2d, strip_y_rescale(strip, 1));
93 return rect;
94}
95
97#define RETIME_KEY_MOUSEOVER_THRESHOLD (16.0f * UI_SCALE_FAC)
98
99rctf strip_retiming_keys_box_get(const Scene *scene, const View2D *v2d, const Strip *strip)
100{
101 rctf rect = strip_box_get(scene, v2d, strip);
102 rect.ymax = KEY_CENTER + KEY_SIZE / 2;
103 rect.ymin = KEY_CENTER - KEY_SIZE / 2;
104 return rect;
105}
106
107int left_fake_key_frame_get(const bContext *C, const Strip *strip)
108{
109 const Scene *scene = CTX_data_sequencer_scene(C);
110 const float scene_fps = float(scene->r.frs_sec) / float(scene->r.frs_sec_base);
111 const int sound_offset = seq::time_get_rounded_sound_offset(strip, scene_fps);
112 const int content_start = seq::time_start_frame_get(strip) + sound_offset;
113 return max_ii(content_start, seq::time_left_handle_frame_get(scene, strip));
114}
115
116int right_fake_key_frame_get(const bContext *C, const Strip *strip)
117{
118 const Scene *scene = CTX_data_sequencer_scene(C);
119 const float scene_fps = float(scene->r.frs_sec) / float(scene->r.frs_sec_base);
120 const int sound_offset = seq::time_get_rounded_sound_offset(strip, scene_fps);
121 const int content_end = seq::time_content_end_frame_get(scene, strip) + sound_offset;
122 return min_ii(content_end, seq::time_right_handle_frame_get(scene, strip));
123}
124
126 const Strip *strip,
127 const int mval[2],
128 int &r_frame)
129{
130 const Scene *scene = CTX_data_sequencer_scene(C);
131 const View2D *v2d = UI_view2d_fromcontext(C);
132
133 rctf box = strip_retiming_keys_box_get(scene, v2d, strip);
134 if (!BLI_rctf_isect_pt(&box, mval[0], mval[1])) {
135 return false;
136 }
137
138 const int left_frame = left_fake_key_frame_get(C, strip);
139 const float left_distance = fabs(UI_view2d_view_to_region_x(v2d, left_frame) - mval[0]);
140
141 const int right_frame = right_fake_key_frame_get(C, strip);
142 const int right_x = right_frame;
143 const float right_distance = fabs(UI_view2d_view_to_region_x(v2d, right_x) - mval[0]);
144
145 r_frame = (left_distance < right_distance) ? left_frame : right_frame;
146
147 /* Fake key threshold is doubled to make them easier to select. */
148 return min_ff(left_distance, right_distance) < RETIME_KEY_MOUSEOVER_THRESHOLD * 2;
149}
150
151void realize_fake_keys(const Scene *scene, Strip *strip)
152{
154 seq::retiming_add_key(scene, strip, seq::time_left_handle_frame_get(scene, strip));
155 seq::retiming_add_key(scene, strip, seq::time_right_handle_frame_get(scene, strip));
156}
157
158SeqRetimingKey *try_to_realize_fake_keys(const bContext *C, Strip *strip, const int mval[2])
159{
161 SeqRetimingKey *key = nullptr;
162
163 int key_frame;
164 if (retiming_fake_key_frame_clicked(C, strip, mval, key_frame)) {
165 realize_fake_keys(scene, strip);
166 key = seq::retiming_key_get_by_timeline_frame(scene, strip, key_frame);
167 }
168 return key;
169}
170
172 const Strip *strip,
173 const int mval[2])
174{
175 const Scene *scene = CTX_data_sequencer_scene(C);
176 const View2D *v2d = UI_view2d_fromcontext(C);
177
178 int best_distance = INT_MAX;
179 SeqRetimingKey *best_key = nullptr;
180
181 for (SeqRetimingKey &key : seq::retiming_keys_get(strip)) {
183 fabsf(UI_view2d_view_to_region_x(v2d, key_x_get(scene, strip, &key)) - mval[0]));
184
185 int threshold = RETIME_KEY_MOUSEOVER_THRESHOLD;
186 if (key_x_get(scene, strip, &key) == seq::time_left_handle_frame_get(scene, strip) ||
187 key_x_get(scene, strip, &key) == seq::time_right_handle_frame_get(scene, strip))
188 {
189 threshold *= 2; /* Make first and last key easier to select. */
190 }
191
192 if (distance < threshold && distance < best_distance) {
193 best_distance = distance;
194 best_key = &key;
195 }
196 }
197
198 return best_key;
199}
200
201SeqRetimingKey *retiming_mouseover_key_get(const bContext *C, const int mval[2], Strip **r_strip)
202{
203 const Scene *scene = CTX_data_sequencer_scene(C);
204 const View2D *v2d = UI_view2d_fromcontext(C);
205 for (Strip *strip : sequencer_visible_strips_get(C)) {
206 if (!seq::retiming_data_is_editable(strip)) {
207 continue;
208 }
209
210 rctf box = strip_retiming_keys_box_get(scene, v2d, strip);
211 if (!BLI_rctf_isect_pt(&box, mval[0], mval[1])) {
212 continue;
213 }
214
215 if (r_strip != nullptr) {
216 *r_strip = strip;
217 }
218
220
221 if (key == nullptr) {
222 continue;
223 }
224
225 return key;
226 }
227
228 return nullptr;
229}
230
231static bool can_draw_retiming(const TimelineDrawContext *timeline_ctx,
232 const StripDrawContext &strip_ctx)
233{
234 if (timeline_ctx->ed == nullptr) {
235 return false;
236 }
237
238 if (!retiming_keys_can_be_displayed(timeline_ctx->sseq)) {
239 return false;
240 }
241
242 if (!seq::retiming_is_allowed(strip_ctx.strip)) {
243 return false;
244 }
245
246 if (!strip_ctx.can_draw_retiming_overlay) {
247 return false;
248 }
249
250 return true;
251}
252
253/* -------------------------------------------------------------------- */
256
257static void retime_key_draw(const TimelineDrawContext *timeline_ctx,
258 const StripDrawContext &strip_ctx,
259 const SeqRetimingKey *key,
260 const KeyframeShaderBindings &sh_bindings)
261{
262 const Scene *scene = timeline_ctx->scene;
263 const View2D *v2d = timeline_ctx->v2d;
264 Strip *strip = strip_ctx.strip;
265
266 const float key_x = key_x_get(scene, strip, key);
267 const rctf strip_box = strip_box_get(scene, v2d, strip);
268 if (!BLI_rctf_isect_x(&strip_box, UI_view2d_view_to_region_x(v2d, key_x))) {
269 return; /* Key out of the strip bounds. */
270 }
271
274 key_type = BEZT_KEYTYPE_BREAKDOWN;
275 }
277 key_type = BEZT_KEYTYPE_MOVEHOLD;
278 }
279
280 const bool is_selected = timeline_ctx->retiming_selection.contains(
281 const_cast<SeqRetimingKey *>(key));
282 const int size = KEY_SIZE;
283 const float bottom = KEY_CENTER;
284
285 /* Ensure, that key is always inside of strip. */
286 const float right_pos_max = UI_view2d_view_to_region_x(v2d, strip_ctx.right_handle) - (size / 2);
287 const float left_pos_min = UI_view2d_view_to_region_x(v2d, strip_ctx.left_handle) + (size / 2);
288 float key_position = UI_view2d_view_to_region_x(v2d, key_x);
289 CLAMP(key_position, left_pos_min, right_pos_max);
290 const float alpha = seq::retiming_data_is_editable(strip) ? 1.0f : 0.3f;
291
292 draw_keyframe_shape(key_position,
293 bottom,
294 size,
295 is_selected && seq::retiming_data_is_editable(strip),
296 key_type,
298 alpha,
299 &sh_bindings,
300 0,
301 0);
302}
303
305 const StripDrawContext &strip_ctx)
306{
307 if (!can_draw_retiming(timeline_ctx, strip_ctx) ||
308 seq::retiming_keys_count(strip_ctx.strip) == 0)
309 {
310 return;
311 }
312
313 const Strip *strip = strip_ctx.strip;
314 const View2D *v2d = timeline_ctx->v2d;
315 const Scene *scene = timeline_ctx->scene;
316 const float left_handle_position = UI_view2d_view_to_region_x(v2d, strip_ctx.left_handle);
317 const float right_handle_position = UI_view2d_view_to_region_x(v2d, strip_ctx.right_handle);
318
319 for (const SeqRetimingKey &key : seq::retiming_keys_get(strip)) {
320 if (key_x_get(scene, strip, &key) == strip_ctx.left_handle || key.strip_frame_index == 0) {
321 continue;
322 }
323
324 float key_position = UI_view2d_view_to_region_x(v2d, key_x_get(scene, strip, &key));
325 float prev_key_position = UI_view2d_view_to_region_x(v2d, key_x_get(scene, strip, &key - 1));
326 if (prev_key_position > right_handle_position || key_position < left_handle_position) {
327 /* Don't draw highlights for out of bounds retiming keys. */
328 continue;
329 }
330 prev_key_position = max_ff(prev_key_position, left_handle_position);
331 key_position = min_ff(key_position, right_handle_position);
332
333 const int size = KEY_SIZE;
334 const float y_center = KEY_CENTER;
335
336 const float width_fac = 0.5f;
337 const float bottom = y_center - size * width_fac;
338 const float top = y_center + size * width_fac;
339
340 uchar color[4];
342 (timeline_ctx->retiming_selection.contains(const_cast<SeqRetimingKey *>(&key)) ||
343 timeline_ctx->retiming_selection.contains(const_cast<SeqRetimingKey *>(&key - 1))))
344 {
345 color[0] = 166;
346 color[1] = 127;
347 color[2] = 51;
348 color[3] = 255;
349 }
350 else {
351 color[0] = 0;
352 color[1] = 0;
353 color[2] = 0;
354 color[3] = 25;
355 }
356 timeline_ctx->quads->add_quad(prev_key_position, bottom, key_position, top, color);
357 }
358}
359
360static SeqRetimingKey fake_retiming_key_init(const Scene *scene, const Strip *strip, int key_x)
361{
362 const float scene_fps = float(scene->r.frs_sec) / float(scene->r.frs_sec_base);
363 const int sound_offset = seq::time_get_rounded_sound_offset(strip, scene_fps);
364 SeqRetimingKey fake_key = {0};
365 fake_key.strip_frame_index = (key_x - seq::time_start_frame_get(strip) - sound_offset) *
367 fake_key.flag = 0;
368 return fake_key;
369}
370
371/* If there are no keys, draw fake keys and create real key when they are selected. */
372/* TODO: would be nice to draw continuity between fake keys. */
373static bool fake_keys_draw(const TimelineDrawContext *timeline_ctx,
374 const StripDrawContext &strip_ctx,
375 const KeyframeShaderBindings &sh_bindings)
376{
377 const Strip *strip = strip_ctx.strip;
378 const Scene *scene = timeline_ctx->scene;
379
381 return false;
382 }
383
384 const int left_key_frame = left_fake_key_frame_get(timeline_ctx->C, strip);
385 if (seq::retiming_key_get_by_timeline_frame(scene, strip, left_key_frame) == nullptr) {
386 SeqRetimingKey fake_key = fake_retiming_key_init(scene, strip, left_key_frame);
387 retime_key_draw(timeline_ctx, strip_ctx, &fake_key, sh_bindings);
388 }
389
390 int right_key_frame = right_fake_key_frame_get(timeline_ctx->C, strip);
391 if (seq::retiming_key_get_by_timeline_frame(scene, strip, right_key_frame) == nullptr) {
392 SeqRetimingKey fake_key = fake_retiming_key_init(scene, strip, right_key_frame);
393 retime_key_draw(timeline_ctx, strip_ctx, &fake_key, sh_bindings);
394 }
395 return true;
396}
397
400{
401 if (strips.is_empty()) {
402 return;
403 }
404 if (timeline_ctx->ed == nullptr || !retiming_keys_can_be_displayed(timeline_ctx->sseq)) {
405 return;
406 }
407
409 wmOrtho2_region_pixelspace(timeline_ctx->region);
410
411 const View2D *v2d = timeline_ctx->v2d;
412
414 KeyframeShaderBindings sh_bindings;
415 sh_bindings.pos_id = GPU_vertformat_attr_add(
416 format, "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
417 sh_bindings.size_id = GPU_vertformat_attr_add(
418 format, "size", blender::gpu::VertAttrType::SFLOAT_32);
419 sh_bindings.color_id = GPU_vertformat_attr_add(
420 format, "color", blender::gpu::VertAttrType::UNORM_8_8_8_8);
422 format, "outlineColor", blender::gpu::VertAttrType::UNORM_8_8_8_8);
423 sh_bindings.flags_id = GPU_vertformat_attr_add(
424 format, "flags", blender::gpu::VertAttrType::UINT_32);
425
428 immUniform1f("outline_scale", 1.0f);
429 immUniform2f("ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
430
431 constexpr int MAX_KEYS_IN_BATCH = 1024;
432 int point_counter = 0;
433 immBeginAtMost(GPU_PRIM_POINTS, MAX_KEYS_IN_BATCH);
434
435 for (const StripDrawContext &strip_ctx : strips) {
436 if (!can_draw_retiming(timeline_ctx, strip_ctx)) {
437 continue;
438 }
439 if (fake_keys_draw(timeline_ctx, strip_ctx, sh_bindings)) {
440 point_counter += 2;
441 }
442
443 for (const SeqRetimingKey &key : seq::retiming_keys_get(strip_ctx.strip)) {
444 retime_key_draw(timeline_ctx, strip_ctx, &key, sh_bindings);
445 point_counter++;
446
447 /* Next key plus possible two fake keys for next sequence would need at
448 * most 3 points, so restart the batch if we're close to that. */
449 if (point_counter + 3 >= MAX_KEYS_IN_BATCH) {
450 immEnd();
451 immBeginAtMost(GPU_PRIM_POINTS, MAX_KEYS_IN_BATCH);
452 point_counter = 0;
453 }
454 }
455 }
456
457 immEnd();
460
462}
463
465
466/* -------------------------------------------------------------------- */
469
470static size_t label_str_get(const Strip *strip,
471 const SeqRetimingKey *key,
472 char *r_label_str,
473 const size_t label_str_maxncpy)
474{
475 const SeqRetimingKey *next_key = key + 1;
477 const float prev_speed = seq::retiming_key_speed_get(strip, key);
478 const float next_speed = seq::retiming_key_speed_get(strip, next_key + 1);
479 return BLI_snprintf_utf8_rlen(r_label_str,
480 label_str_maxncpy,
481 "%d%% - %d%%",
482 round_fl_to_int(prev_speed * 100.0f),
483 round_fl_to_int(next_speed * 100.0f));
484 }
485 const float speed = seq::retiming_key_speed_get(strip, next_key);
487 r_label_str, label_str_maxncpy, "%d%%", round_fl_to_int(speed * 100.0f));
488}
489
490static bool label_rect_get(const TimelineDrawContext *timeline_ctx,
491 const StripDrawContext &strip_ctx,
492 const SeqRetimingKey *key,
493 const char *label_str,
494 const size_t label_len,
495 rctf *rect)
496{
497 const bContext *C = timeline_ctx->C;
498 const Scene *scene = timeline_ctx->scene;
499 const SeqRetimingKey *next_key = key + 1;
500 const float width = pixels_to_view_width(C, BLF_width(BLF_default(), label_str, label_len));
501 const float height = pixels_to_view_height(C, BLF_height(BLF_default(), label_str, label_len));
502 const float xmin = max_ff(strip_ctx.left_handle, key_x_get(scene, strip_ctx.strip, key));
503 const float xmax = min_ff(strip_ctx.right_handle, key_x_get(scene, strip_ctx.strip, next_key));
504
505 rect->xmin = (xmin + xmax - width) / 2;
506 rect->xmax = rect->xmin + width;
507 rect->ymin = strip_y_rescale(strip_ctx.strip, 0) + pixels_to_view_height(C, 5);
508 rect->ymax = rect->ymin + height;
509
510 return width < xmax - xmin - pixels_to_view_width(C, KEY_SIZE);
511}
512
513static void retime_speed_text_draw(const TimelineDrawContext *timeline_ctx,
514 const StripDrawContext &strip_ctx,
515 const SeqRetimingKey *key)
516{
517 const Strip *strip = strip_ctx.strip;
518 const Scene *scene = timeline_ctx->scene;
519
520 if (seq::retiming_is_last_key(strip, key)) {
521 return;
522 }
523
524 const SeqRetimingKey *next_key = key + 1;
525 if (key_x_get(scene, strip, next_key) < strip_ctx.left_handle ||
526 key_x_get(scene, strip, key) > strip_ctx.right_handle)
527 {
528 return; /* Label out of strip bounds. */
529 }
530
531 char label_str[40];
532 rctf label_rect;
533 size_t label_len = label_str_get(strip, key, label_str, sizeof(label_str));
534
535 if (!label_rect_get(timeline_ctx, strip_ctx, key, label_str, label_len, &label_rect)) {
536 return; /* Not enough space to draw the label. */
537 }
538
539 uchar col[4] = {255, 255, 255, 255};
540 if ((strip->flag & SELECT) == 0) {
541 memset(col, 0, sizeof(col));
542 col[3] = 255;
543 }
544
546 timeline_ctx->v2d, label_rect.xmin, label_rect.ymin, label_str, label_len, col);
547}
548
550 const StripDrawContext &strip_ctx)
551{
552 if (!can_draw_retiming(timeline_ctx, strip_ctx)) {
553 return;
554 }
555
556 for (const SeqRetimingKey &key : seq::retiming_keys_get(strip_ctx.strip)) {
557 retime_speed_text_draw(timeline_ctx, strip_ctx, &key);
558 }
559
560 UI_view2d_view_ortho(timeline_ctx->v2d);
561}
562
564
565} // namespace blender::ed::vse
Scene * CTX_data_sequencer_scene(const bContext *C)
float BLF_height(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2)
Definition blf.cc:837
int BLF_default()
float BLF_width(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2)
Definition blf.cc:802
MINLINE int round_fl_to_int(float a)
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
bool BLI_rctf_isect_x(const rctf *rect, float x)
Definition rct.cc:93
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:198
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:194
bool BLI_rctf_isect_pt(const struct rctf *rect, float x, float y)
size_t BLI_snprintf_utf8_rlen(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
unsigned char uchar
#define CLAMP(a, b, c)
eBezTriple_KeyframeType
@ BEZT_KEYTYPE_BREAKDOWN
@ BEZT_KEYTYPE_MOVEHOLD
@ BEZT_KEYTYPE_KEYFRAME
#define STRIP_OFSBOTTOM
#define STRIP_OFSTOP
@ SEQ_TIMELINE_SHOW_STRIP_RETIMING
@ SEQ_SHOW_OVERLAY
@ KEYFRAME_SHAPE_BOTH
void immEnd()
void immUnbindProgram()
void immBindBuiltinProgram(GPUBuiltinShader shader_id)
void immUniform2f(const char *name, float x, float y)
void immBeginAtMost(GPUPrimType, uint max_vertex_len)
void immUniform1f(const char *name, float x)
GPUVertFormat * immVertexFormat()
void GPU_matrix_push_projection()
void GPU_matrix_pop_projection()
@ GPU_PRIM_POINTS
@ GPU_SHADER_KEYFRAME_SHAPE
void GPU_program_point_size(bool enable)
Definition gpu_state.cc:180
uint GPU_vertformat_attr_add(GPUVertFormat *format, blender::StringRef name, blender::gpu::VertAttrType type)
#define C
Definition RandGen.cpp:29
char char char char void UI_view2d_text_cache_add(View2D *v2d, float x, float y, const char *str, size_t str_len, const unsigned char col[4])
Definition view2d.cc:2082
float UI_view2d_view_to_region_y(const View2D *v2d, float y)
Definition view2d.cc:1696
void UI_view2d_view_ortho(const View2D *v2d)
Definition view2d.cc:1095
View2D * UI_view2d_fromcontext(const bContext *C)
Definition view2d.cc:1855
float UI_view2d_view_to_region_x(const View2D *v2d, float x)
Definition view2d.cc:1691
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
bool contains(const Key &key) const
Definition BLI_map.hh:353
constexpr bool is_empty() const
Definition BLI_span.hh:260
void add_quad(float x1, float y1, float x2, float y2, const uchar color[4])
nullptr float
#define SELECT
uint col
uint top
float distance(VecOp< float, D >, VecOp< float, D >) RET
void draw_keyframe_shape(const float x, const float y, float size, const bool sel, const eBezTriple_KeyframeType key_type, const eKeyframeShapeDrawOpts mode, const float alpha, const KeyframeShaderBindings *sh_bindings, const short handle_type, const short extreme_type)
format
ccl_device_inline float2 fabs(const float2 a)
static void retime_key_draw(const TimelineDrawContext *timeline_ctx, const StripDrawContext &strip_ctx, const SeqRetimingKey *key, const KeyframeShaderBindings &sh_bindings)
void sequencer_retiming_draw_continuity(const TimelineDrawContext *timeline_ctx, const StripDrawContext &strip_ctx)
static rctf strip_box_get(const Scene *scene, const View2D *v2d, const Strip *strip)
SeqRetimingKey * retiming_mouseover_key_get(const bContext *C, const int mval[2], Strip **r_strip)
int right_fake_key_frame_get(const bContext *C, const Strip *strip)
void sequencer_retiming_speed_draw(const TimelineDrawContext *timeline_ctx, const StripDrawContext &strip_ctx)
static float pixels_to_view_height(const bContext *C, const float height)
static bool can_draw_retiming(const TimelineDrawContext *timeline_ctx, const StripDrawContext &strip_ctx)
static float key_x_get(const Scene *scene, const Strip *strip, const SeqRetimingKey *key)
void sequencer_retiming_keys_draw(const TimelineDrawContext *timeline_ctx, blender::Span< StripDrawContext > strips)
static bool fake_keys_draw(const TimelineDrawContext *timeline_ctx, const StripDrawContext &strip_ctx, const KeyframeShaderBindings &sh_bindings)
SeqRetimingKey * try_to_realize_fake_keys(const bContext *C, Strip *strip, const int mval[2])
static float strip_end_screenspace_get(const Scene *scene, const View2D *v2d, const Strip *strip)
rctf strip_retiming_keys_box_get(const Scene *scene, const View2D *v2d, const Strip *strip)
bool retiming_keys_can_be_displayed(const SpaceSeq *sseq)
static size_t label_str_get(const Strip *strip, const SeqRetimingKey *key, char *r_label_str, const size_t label_str_maxncpy)
void realize_fake_keys(const Scene *scene, Strip *strip)
static SeqRetimingKey * mouse_over_key_get_from_strip(const bContext *C, const Strip *strip, const int mval[2])
int left_fake_key_frame_get(const bContext *C, const Strip *strip)
static void retime_speed_text_draw(const TimelineDrawContext *timeline_ctx, const StripDrawContext &strip_ctx, const SeqRetimingKey *key)
static float pixels_to_view_width(const bContext *C, const float width)
static float strip_y_rescale(const Strip *strip, const float y_value)
blender::Vector< Strip * > sequencer_visible_strips_get(const bContext *C)
static bool label_rect_get(const TimelineDrawContext *timeline_ctx, const StripDrawContext &strip_ctx, const SeqRetimingKey *key, const char *label_str, const size_t label_len, rctf *rect)
static float strip_start_screenspace_get(const Scene *scene, const View2D *v2d, const Strip *strip)
static bool retiming_fake_key_frame_clicked(const bContext *C, const Strip *strip, const int mval[2], int &r_frame)
static SeqRetimingKey fake_retiming_key_init(const Scene *scene, const Strip *strip, int key_x)
int time_right_handle_frame_get(const Scene *scene, const Strip *strip)
bool retiming_key_is_transition_start(const SeqRetimingKey *key)
float time_content_end_frame_get(const Scene *scene, const Strip *strip)
int retiming_keys_count(const Strip *strip)
float time_media_playback_rate_factor_get(const Strip *strip, const float scene_fps)
Definition strip_time.cc:41
int retiming_key_timeline_frame_get(const Scene *scene, const Strip *strip, const SeqRetimingKey *key)
MutableSpan< SeqRetimingKey > retiming_keys_get(const Strip *strip)
void retiming_data_ensure(Strip *strip)
int time_left_handle_frame_get(const Scene *, const Strip *strip)
int time_get_rounded_sound_offset(const Strip *strip, const float frames_per_second)
float time_start_frame_get(const Strip *strip)
SeqRetimingKey * retiming_key_get_by_timeline_frame(const Scene *scene, const Strip *strip, const int timeline_frame)
bool retiming_is_active(const Strip *strip)
bool retiming_key_is_transition_type(const SeqRetimingKey *key)
bool retiming_key_is_freeze_frame(const SeqRetimingKey *key)
bool retiming_data_is_editable(const Strip *strip)
float retiming_key_speed_get(const Strip *strip, const SeqRetimingKey *key)
bool retiming_is_allowed(const Strip *strip)
SeqRetimingKey * retiming_add_key(const Scene *scene, Strip *strip, const int timeline_frame)
bool retiming_is_last_key(const Strip *strip, const SeqRetimingKey *key)
#define fabsf
#define KEY_CENTER
#define KEY_SIZE
#define RETIME_KEY_MOUSEOVER_THRESHOLD
struct RenderData r
struct SequencerTimelineOverlay timeline_overlay
blender::Map< SeqRetimingKey *, Strip * > retiming_selection
float xmax
float xmin
float ymax
float ymin
void wmOrtho2_region_pixelspace(const ARegion *region)