Blender V4.5
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.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 if (seq::retiming_is_last_key(strip, key)) {
60 return seq::retiming_key_timeline_frame_get(scene, strip, key) + 1;
61 }
62 return seq::retiming_key_timeline_frame_get(scene, strip, key);
63}
64
65static float pixels_to_view_width(const bContext *C, const float width)
66{
67 const View2D *v2d = UI_view2d_fromcontext(C);
68 float scale_x = UI_view2d_view_to_region_x(v2d, 1) - UI_view2d_view_to_region_x(v2d, 0.0f);
69 return width / scale_x;
70}
71
72static float pixels_to_view_height(const bContext *C, const float height)
73{
74 const View2D *v2d = UI_view2d_fromcontext(C);
75 float scale_y = UI_view2d_view_to_region_y(v2d, 1) - UI_view2d_view_to_region_y(v2d, 0.0f);
76 return height / scale_y;
77}
78
79static float strip_start_screenspace_get(const Scene *scene, const View2D *v2d, const Strip *strip)
80{
82}
83
84static float strip_end_screenspace_get(const Scene *scene, const View2D *v2d, const Strip *strip)
85{
87}
88
89static rctf strip_box_get(const Scene *scene, const View2D *v2d, const Strip *strip)
90{
91 rctf rect;
92 rect.xmin = strip_start_screenspace_get(scene, v2d, strip);
93 rect.xmax = strip_end_screenspace_get(scene, v2d, strip);
94 rect.ymin = UI_view2d_view_to_region_y(v2d, strip_y_rescale(strip, 0));
95 rect.ymax = UI_view2d_view_to_region_y(v2d, strip_y_rescale(strip, 1));
96 return rect;
97}
98
100#define RETIME_KEY_MOUSEOVER_THRESHOLD (16.0f * UI_SCALE_FAC)
101
102rctf strip_retiming_keys_box_get(const Scene *scene, const View2D *v2d, const Strip *strip)
103{
104 rctf rect = strip_box_get(scene, v2d, strip);
105 rect.ymax = KEY_CENTER + KEY_SIZE / 2;
106 rect.ymin = KEY_CENTER - KEY_SIZE / 2;
107 return rect;
108}
109
110int left_fake_key_frame_get(const bContext *C, const Strip *strip)
111{
112 const Scene *scene = CTX_data_scene(C);
113 const float scene_fps = float(scene->r.frs_sec) / float(scene->r.frs_sec_base);
114 const int sound_offset = seq::time_get_rounded_sound_offset(strip, scene_fps);
115 const int content_start = seq::time_start_frame_get(strip) + sound_offset;
116 return max_ii(content_start, seq::time_left_handle_frame_get(scene, strip));
117}
118
119int right_fake_key_frame_get(const bContext *C, const Strip *strip)
120{
121 const Scene *scene = CTX_data_scene(C);
122 const float scene_fps = float(scene->r.frs_sec) / float(scene->r.frs_sec_base);
123 const int sound_offset = seq::time_get_rounded_sound_offset(strip, scene_fps);
124 const int content_end = seq::time_content_end_frame_get(scene, strip) - 1 + sound_offset;
125 return min_ii(content_end, seq::time_right_handle_frame_get(scene, strip));
126}
127
129 const Strip *strip,
130 const int mval[2],
131 int &r_frame)
132{
133 const Scene *scene = CTX_data_scene(C);
134 const View2D *v2d = UI_view2d_fromcontext(C);
135
136 rctf box = strip_retiming_keys_box_get(scene, v2d, strip);
137 if (!BLI_rctf_isect_pt(&box, mval[0], mval[1])) {
138 return false;
139 }
140
141 const int left_frame = left_fake_key_frame_get(C, strip);
142 const float left_distance = fabs(UI_view2d_view_to_region_x(v2d, left_frame) - mval[0]);
143
144 const int right_frame = right_fake_key_frame_get(C, strip);
145 int right_x = right_frame;
146 /* `key_x_get()` compensates 1 frame offset of last key, however this can not
147 * be conveyed via `fake_key` alone. Therefore the same offset must be emulated. */
148 if (seq::time_right_handle_frame_get(scene, strip) >=
150 {
151 right_x += 1;
152 }
153 const float right_distance = fabs(UI_view2d_view_to_region_x(v2d, right_x) - mval[0]);
154
155 r_frame = (left_distance < right_distance) ? left_frame : right_frame;
156
157 /* Fake key threshold is doubled to make them easier to select. */
158 return min_ff(left_distance, right_distance) < RETIME_KEY_MOUSEOVER_THRESHOLD * 2;
159}
160
161void realize_fake_keys(const Scene *scene, Strip *strip)
162{
164 seq::retiming_add_key(scene, strip, seq::time_left_handle_frame_get(scene, strip));
165 seq::retiming_add_key(scene, strip, seq::time_right_handle_frame_get(scene, strip));
166}
167
168SeqRetimingKey *try_to_realize_fake_keys(const bContext *C, Strip *strip, const int mval[2])
169{
170 Scene *scene = CTX_data_scene(C);
171 SeqRetimingKey *key = nullptr;
172
173 int key_frame;
174 if (retiming_fake_key_frame_clicked(C, strip, mval, key_frame)) {
175 realize_fake_keys(scene, strip);
176 key = seq::retiming_key_get_by_timeline_frame(scene, strip, key_frame);
177 }
178 return key;
179}
180
182 const Strip *strip,
183 const int mval[2])
184{
185 const Scene *scene = CTX_data_scene(C);
186 const View2D *v2d = UI_view2d_fromcontext(C);
187
188 int best_distance = INT_MAX;
189 SeqRetimingKey *best_key = nullptr;
190
191 for (SeqRetimingKey &key : seq::retiming_keys_get(strip)) {
193 fabsf(UI_view2d_view_to_region_x(v2d, key_x_get(scene, strip, &key)) - mval[0]));
194
195 int threshold = RETIME_KEY_MOUSEOVER_THRESHOLD;
196 if (key_x_get(scene, strip, &key) == seq::time_left_handle_frame_get(scene, strip) ||
197 key_x_get(scene, strip, &key) == seq::time_right_handle_frame_get(scene, strip))
198 {
199 threshold *= 2; /* Make first and last key easier to select. */
200 }
201
202 if (distance < threshold && distance < best_distance) {
203 best_distance = distance;
204 best_key = &key;
205 }
206 }
207
208 return best_key;
209}
210
211SeqRetimingKey *retiming_mouseover_key_get(const bContext *C, const int mval[2], Strip **r_strip)
212{
213 const Scene *scene = CTX_data_scene(C);
214 const View2D *v2d = UI_view2d_fromcontext(C);
215 for (Strip *strip : sequencer_visible_strips_get(C)) {
216 rctf box = strip_retiming_keys_box_get(scene, v2d, strip);
217 if (!BLI_rctf_isect_pt(&box, mval[0], mval[1])) {
218 continue;
219 }
220
221 if (r_strip != nullptr) {
222 *r_strip = strip;
223 }
224
226
227 if (key == nullptr) {
228 continue;
229 }
230
231 return key;
232 }
233
234 return nullptr;
235}
236
237static bool can_draw_retiming(const TimelineDrawContext *timeline_ctx,
238 const StripDrawContext &strip_ctx)
239{
240 if (timeline_ctx->ed == nullptr) {
241 return false;
242 }
243
244 if (!retiming_keys_can_be_displayed(timeline_ctx->sseq)) {
245 return false;
246 }
247
248 if (!seq::retiming_is_allowed(strip_ctx.strip)) {
249 return false;
250 }
251
252 if (!strip_ctx.can_draw_retiming_overlay) {
253 return false;
254 }
255
256 return true;
257}
258
259/* -------------------------------------------------------------------- */
262
263static void retime_key_draw(const TimelineDrawContext *timeline_ctx,
264 const StripDrawContext &strip_ctx,
265 const SeqRetimingKey *key,
266 const KeyframeShaderBindings &sh_bindings)
267{
268 const Scene *scene = timeline_ctx->scene;
269 const View2D *v2d = timeline_ctx->v2d;
270 Strip *strip = strip_ctx.strip;
271
272 const float key_x = key_x_get(scene, strip, key);
273 const rctf strip_box = strip_box_get(scene, v2d, strip);
274 if (!BLI_rctf_isect_x(&strip_box, UI_view2d_view_to_region_x(v2d, key_x))) {
275 return; /* Key out of the strip bounds. */
276 }
277
280 key_type = BEZT_KEYTYPE_BREAKDOWN;
281 }
283 key_type = BEZT_KEYTYPE_MOVEHOLD;
284 }
285
286 const bool is_selected = timeline_ctx->retiming_selection.contains(
287 const_cast<SeqRetimingKey *>(key));
288 const int size = KEY_SIZE;
289 const float bottom = KEY_CENTER;
290
291 /* Ensure, that key is always inside of strip. */
292 const float right_pos_max = UI_view2d_view_to_region_x(v2d, strip_ctx.right_handle) - (size / 2);
293 const float left_pos_min = UI_view2d_view_to_region_x(v2d, strip_ctx.left_handle) + (size / 2);
294 float key_position = UI_view2d_view_to_region_x(v2d, key_x);
295 CLAMP(key_position, left_pos_min, right_pos_max);
296 const float alpha = seq::retiming_data_is_editable(strip) ? 1.0f : 0.3f;
297
298 draw_keyframe_shape(key_position,
299 bottom,
300 size,
301 is_selected && seq::retiming_data_is_editable(strip),
302 key_type,
304 alpha,
305 &sh_bindings,
306 0,
307 0);
308}
309
311 const StripDrawContext &strip_ctx)
312{
313 if (!can_draw_retiming(timeline_ctx, strip_ctx) ||
314 seq::retiming_keys_count(strip_ctx.strip) == 0)
315 {
316 return;
317 }
318
319 const Strip *strip = strip_ctx.strip;
320 const View2D *v2d = timeline_ctx->v2d;
321 const Scene *scene = timeline_ctx->scene;
322 const float left_handle_position = UI_view2d_view_to_region_x(v2d, strip_ctx.left_handle);
323 const float right_handle_position = UI_view2d_view_to_region_x(v2d, strip_ctx.right_handle);
324
325 for (const SeqRetimingKey &key : seq::retiming_keys_get(strip)) {
326 if (key_x_get(scene, strip, &key) == strip_ctx.left_handle || key.strip_frame_index == 0) {
327 continue;
328 }
329
330 float key_position = UI_view2d_view_to_region_x(v2d, key_x_get(scene, strip, &key));
331 float prev_key_position = UI_view2d_view_to_region_x(v2d, key_x_get(scene, strip, &key - 1));
332 if (prev_key_position > right_handle_position || key_position < left_handle_position) {
333 /* Don't draw highlights for out of bounds retiming keys. */
334 continue;
335 }
336 prev_key_position = max_ff(prev_key_position, left_handle_position);
337 key_position = min_ff(key_position, right_handle_position);
338
339 const int size = KEY_SIZE;
340 const float y_center = KEY_CENTER;
341
342 const float width_fac = 0.5f;
343 const float bottom = y_center - size * width_fac;
344 const float top = y_center + size * width_fac;
345
346 uchar color[4];
348 (timeline_ctx->retiming_selection.contains(const_cast<SeqRetimingKey *>(&key)) ||
349 timeline_ctx->retiming_selection.contains(const_cast<SeqRetimingKey *>(&key - 1))))
350 {
351 color[0] = 166;
352 color[1] = 127;
353 color[2] = 51;
354 color[3] = 255;
355 }
356 else {
357 color[0] = 0;
358 color[1] = 0;
359 color[2] = 0;
360 color[3] = 25;
361 }
362 timeline_ctx->quads->add_quad(prev_key_position, bottom, key_position, top, color);
363 }
364}
365
366static SeqRetimingKey fake_retiming_key_init(const Scene *scene, const Strip *strip, int key_x)
367{
368 const float scene_fps = float(scene->r.frs_sec) / float(scene->r.frs_sec_base);
369 const int sound_offset = seq::time_get_rounded_sound_offset(strip, scene_fps);
370 SeqRetimingKey fake_key = {0};
371 fake_key.strip_frame_index = (key_x - seq::time_start_frame_get(strip) - sound_offset) *
373 fake_key.flag = 0;
374 return fake_key;
375}
376
377/* If there are no keys, draw fake keys and create real key when they are selected. */
378/* TODO: would be nice to draw continuity between fake keys. */
379static bool fake_keys_draw(const TimelineDrawContext *timeline_ctx,
380 const StripDrawContext &strip_ctx,
381 const KeyframeShaderBindings &sh_bindings)
382{
383 const Strip *strip = strip_ctx.strip;
384 const Scene *scene = timeline_ctx->scene;
385
387 return false;
388 }
389
390 const int left_key_frame = left_fake_key_frame_get(timeline_ctx->C, strip);
391 if (seq::retiming_key_get_by_timeline_frame(scene, strip, left_key_frame) == nullptr) {
392 SeqRetimingKey fake_key = fake_retiming_key_init(scene, strip, left_key_frame);
393 retime_key_draw(timeline_ctx, strip_ctx, &fake_key, sh_bindings);
394 }
395
396 int right_key_frame = right_fake_key_frame_get(timeline_ctx->C, strip);
397 if (seq::retiming_key_get_by_timeline_frame(scene, strip, right_key_frame) == nullptr) {
398 /* `key_x_get()` compensates 1 frame offset of last key, however this can not
399 * be conveyed via `fake_key` alone. Therefore the same offset must be emulated. */
400 if (strip_ctx.right_handle >= seq::time_content_end_frame_get(scene, strip)) {
401 right_key_frame += 1;
402 }
403 SeqRetimingKey fake_key = fake_retiming_key_init(scene, strip, right_key_frame);
404 retime_key_draw(timeline_ctx, strip_ctx, &fake_key, sh_bindings);
405 }
406 return true;
407}
408
411{
412 if (strips.is_empty()) {
413 return;
414 }
415 if (timeline_ctx->ed == nullptr || !retiming_keys_can_be_displayed(timeline_ctx->sseq)) {
416 return;
417 }
418
420 wmOrtho2_region_pixelspace(timeline_ctx->region);
421
422 const View2D *v2d = timeline_ctx->v2d;
423
425 KeyframeShaderBindings sh_bindings;
428 sh_bindings.color_id = GPU_vertformat_attr_add(
431 format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
433
436 immUniform1f("outline_scale", 1.0f);
437 immUniform2f("ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
438
439 constexpr int MAX_KEYS_IN_BATCH = 1024;
440 int point_counter = 0;
441 immBeginAtMost(GPU_PRIM_POINTS, MAX_KEYS_IN_BATCH);
442
443 for (const StripDrawContext &strip_ctx : strips) {
444 if (!can_draw_retiming(timeline_ctx, strip_ctx)) {
445 continue;
446 }
447 if (fake_keys_draw(timeline_ctx, strip_ctx, sh_bindings)) {
448 point_counter += 2;
449 }
450
451 for (const SeqRetimingKey &key : seq::retiming_keys_get(strip_ctx.strip)) {
452 retime_key_draw(timeline_ctx, strip_ctx, &key, sh_bindings);
453 point_counter++;
454
455 /* Next key plus possible two fake keys for next sequence would need at
456 * most 3 points, so restart the batch if we're close to that. */
457 if (point_counter + 3 >= MAX_KEYS_IN_BATCH) {
458 immEnd();
459 immBeginAtMost(GPU_PRIM_POINTS, MAX_KEYS_IN_BATCH);
460 point_counter = 0;
461 }
462 }
463 }
464
465 immEnd();
468
470}
471
473
474/* -------------------------------------------------------------------- */
477
478static size_t label_str_get(const Strip *strip,
479 const SeqRetimingKey *key,
480 char *r_label_str,
481 const size_t label_str_maxncpy)
482{
483 const SeqRetimingKey *next_key = key + 1;
485 const float prev_speed = seq::retiming_key_speed_get(strip, key);
486 const float next_speed = seq::retiming_key_speed_get(strip, next_key + 1);
487 return BLI_snprintf_rlen(r_label_str,
488 label_str_maxncpy,
489 "%d%% - %d%%",
490 round_fl_to_int(prev_speed * 100.0f),
491 round_fl_to_int(next_speed * 100.0f));
492 }
493 const float speed = seq::retiming_key_speed_get(strip, next_key);
494 return BLI_snprintf_rlen(
495 r_label_str, label_str_maxncpy, "%d%%", round_fl_to_int(speed * 100.0f));
496}
497
498static bool label_rect_get(const TimelineDrawContext *timeline_ctx,
499 const StripDrawContext &strip_ctx,
500 const SeqRetimingKey *key,
501 const char *label_str,
502 const size_t label_len,
503 rctf *rect)
504{
505 const bContext *C = timeline_ctx->C;
506 const Scene *scene = timeline_ctx->scene;
507 const SeqRetimingKey *next_key = key + 1;
508 const float width = pixels_to_view_width(C, BLF_width(BLF_default(), label_str, label_len));
509 const float height = pixels_to_view_height(C, BLF_height(BLF_default(), label_str, label_len));
510 const float xmin = max_ff(strip_ctx.left_handle, key_x_get(scene, strip_ctx.strip, key));
511 const float xmax = min_ff(strip_ctx.right_handle, key_x_get(scene, strip_ctx.strip, next_key));
512
513 rect->xmin = (xmin + xmax - width) / 2;
514 rect->xmax = rect->xmin + width;
515 rect->ymin = strip_y_rescale(strip_ctx.strip, 0) + pixels_to_view_height(C, 5);
516 rect->ymax = rect->ymin + height;
517
518 return width < xmax - xmin - pixels_to_view_width(C, KEY_SIZE);
519}
520
521static void retime_speed_text_draw(const TimelineDrawContext *timeline_ctx,
522 const StripDrawContext &strip_ctx,
523 const SeqRetimingKey *key)
524{
525 const Strip *strip = strip_ctx.strip;
526 const Scene *scene = timeline_ctx->scene;
527
528 if (seq::retiming_is_last_key(strip, key)) {
529 return;
530 }
531
532 const SeqRetimingKey *next_key = key + 1;
533 if (key_x_get(scene, strip, next_key) < strip_ctx.left_handle ||
534 key_x_get(scene, strip, key) > strip_ctx.right_handle)
535 {
536 return; /* Label out of strip bounds. */
537 }
538
539 char label_str[40];
540 rctf label_rect;
541 size_t label_len = label_str_get(strip, key, label_str, sizeof(label_str));
542
543 if (!label_rect_get(timeline_ctx, strip_ctx, key, label_str, label_len, &label_rect)) {
544 return; /* Not enough space to draw the label. */
545 }
546
547 uchar col[4] = {255, 255, 255, 255};
548 if ((strip->flag & SELECT) == 0) {
549 memset(col, 0, sizeof(col));
550 col[3] = 255;
551 }
552
554 timeline_ctx->v2d, label_rect.xmin, label_rect.ymin, label_str, label_len, col);
555}
556
558 const StripDrawContext &strip_ctx)
559{
560 if (!can_draw_retiming(timeline_ctx, strip_ctx)) {
561 return;
562 }
563
564 for (const SeqRetimingKey &key : seq::retiming_keys_get(strip_ctx.strip)) {
565 retime_speed_text_draw(timeline_ctx, strip_ctx, &key);
566 }
567
568 UI_view2d_view_ortho(timeline_ctx->v2d);
569}
570
572
573} // namespace blender::ed::vse
Scene * CTX_data_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:840
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:805
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_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 immUniform2f(const char *name, float x, float y)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
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
@ GPU_FETCH_FLOAT
@ GPU_FETCH_INT_TO_FLOAT_UNIT
@ GPU_FETCH_INT
uint GPU_vertformat_attr_add(GPUVertFormat *, blender::StringRef name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
@ GPU_COMP_U32
@ GPU_COMP_U8
#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:2081
float UI_view2d_view_to_region_y(const View2D *v2d, float y)
Definition view2d.cc:1695
void UI_view2d_view_ortho(const View2D *v2d)
Definition view2d.cc:1095
View2D * UI_view2d_fromcontext(const bContext *C)
Definition view2d.cc:1854
float UI_view2d_view_to_region_x(const View2D *v2d, float x)
Definition view2d.cc:1690
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])
#define SELECT
#define fabsf(x)
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 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)