Blender V4.3
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
9#include "MEM_guardedalloc.h"
10
11#include "BLI_blenlib.h"
12
13#include "DNA_sequence_types.h"
14
15#include "BKE_context.hh"
16#include "BKE_fcurve.hh"
17
18#include "BLF_api.hh"
19
20#include "GPU_batch.hh"
21#include "GPU_matrix.hh"
22#include "GPU_state.hh"
23
24#include "WM_api.hh"
25#include "WM_types.hh"
26
27#include "ED_keyframes_draw.hh"
29#include "ED_screen.hh"
30
31#include "UI_view2d.hh"
32
33#include "SEQ_connect.hh"
34#include "SEQ_retiming.hh"
35#include "SEQ_sequencer.hh"
36#include "SEQ_time.hh"
37
38/* Own include. */
39#include "sequencer_intern.hh"
41
42#define KEY_SIZE (10 * U.pixelsize)
43#define KEY_CENTER (UI_view2d_view_to_region_y(v2d, strip_y_rescale(seq, 0.0f)) + 4 + KEY_SIZE / 2)
44
50
51static float strip_y_rescale(const Sequence *seq, const float y_value)
52{
53 const float y_range = SEQ_STRIP_OFSTOP - SEQ_STRIP_OFSBOTTOM;
54 return (y_value * y_range) + seq->machine + SEQ_STRIP_OFSBOTTOM;
55}
56
57static float key_x_get(const Scene *scene, const Sequence *seq, const SeqRetimingKey *key)
58{
59 if (SEQ_retiming_is_last_key(seq, key)) {
60 return SEQ_retiming_key_timeline_frame_get(scene, seq, key) + 1;
61 }
62 return SEQ_retiming_key_timeline_frame_get(scene, seq, 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,
80 const View2D *v2d,
81 const Sequence *seq)
82{
84}
85
86static float strip_end_screenspace_get(const Scene *scene, const View2D *v2d, const Sequence *seq)
87{
89}
90
91static rctf strip_box_get(const Scene *scene, const View2D *v2d, const Sequence *seq)
92{
93 rctf rect;
94 rect.xmin = strip_start_screenspace_get(scene, v2d, seq);
95 rect.xmax = strip_end_screenspace_get(scene, v2d, seq);
98 return rect;
99}
100
102#define RETIME_KEY_MOUSEOVER_THRESHOLD (16.0f * UI_SCALE_FAC)
103
104rctf seq_retiming_keys_box_get(const Scene *scene, const View2D *v2d, const Sequence *seq)
105{
106 rctf rect = strip_box_get(scene, v2d, seq);
107 rect.ymax = KEY_CENTER + KEY_SIZE / 2;
108 rect.ymin = KEY_CENTER - KEY_SIZE / 2;
109 return rect;
110}
111
113{
114 const Scene *scene = CTX_data_scene(C);
115 int sound_offset = SEQ_time_get_rounded_sound_offset(scene, seq);
116 const int content_start = SEQ_time_start_frame_get(seq) + sound_offset;
117 return max_ii(content_start, SEQ_time_left_handle_frame_get(scene, seq));
118}
119
121{
122 const Scene *scene = CTX_data_scene(C);
123 int sound_offset = SEQ_time_get_rounded_sound_offset(scene, seq);
124 const int content_end = SEQ_time_content_end_frame_get(scene, seq) - 1 + sound_offset;
125 return min_ii(content_end, SEQ_time_right_handle_frame_get(scene, seq));
126}
127
129 const Sequence *seq,
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 = seq_retiming_keys_box_get(scene, v2d, seq);
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, seq);
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, seq);
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. */
149 right_x += 1;
150 }
151 const float right_distance = fabs(UI_view2d_view_to_region_x(v2d, right_x) - mval[0]);
152
153 r_frame = (left_distance < right_distance) ? left_frame : right_frame;
154 return min_ff(left_distance, right_distance) < RETIME_KEY_MOUSEOVER_THRESHOLD;
155}
156
157void realize_fake_keys(const Scene *scene, Sequence *seq)
158{
162}
163
164SeqRetimingKey *try_to_realize_fake_keys(const bContext *C, Sequence *seq, const int mval[2])
165{
166 Scene *scene = CTX_data_scene(C);
167 SeqRetimingKey *key = nullptr;
168
169 int key_frame;
170 if (retiming_fake_key_frame_clicked(C, seq, mval, key_frame)) {
171 realize_fake_keys(scene, seq);
172 key = SEQ_retiming_key_get_by_timeline_frame(scene, seq, key_frame);
173 }
174 return key;
175}
176
178 const Sequence *seq,
179 const int mval[2])
180{
181 const Scene *scene = CTX_data_scene(C);
182 const View2D *v2d = UI_view2d_fromcontext(C);
183
184 int best_distance = INT_MAX;
185 SeqRetimingKey *best_key = nullptr;
186
187 for (SeqRetimingKey &key : SEQ_retiming_keys_get(seq)) {
188 int distance = round_fl_to_int(
189 fabsf(UI_view2d_view_to_region_x(v2d, key_x_get(scene, seq, &key)) - mval[0]));
190
191 int threshold = RETIME_KEY_MOUSEOVER_THRESHOLD;
192 if (key_x_get(scene, seq, &key) == SEQ_time_left_handle_frame_get(scene, seq) ||
193 key_x_get(scene, seq, &key) == SEQ_time_right_handle_frame_get(scene, seq))
194 {
195 threshold *= 2; /* Make first and last key easier to select. */
196 }
197
198 if (distance < threshold && distance < best_distance) {
199 best_distance = distance;
200 best_key = &key;
201 }
202 }
203
204 return best_key;
205}
206
207SeqRetimingKey *retiming_mouseover_key_get(const bContext *C, const int mval[2], Sequence **r_seq)
208{
209 const Scene *scene = CTX_data_scene(C);
210 const View2D *v2d = UI_view2d_fromcontext(C);
211 for (Sequence *seq : sequencer_visible_strips_get(C)) {
212 rctf box = seq_retiming_keys_box_get(scene, v2d, seq);
213 if (!BLI_rctf_isect_pt(&box, mval[0], mval[1])) {
214 continue;
215 }
216
217 if (r_seq != nullptr) {
218 *r_seq = seq;
219 }
220
222
223 if (key == nullptr) {
224 continue;
225 }
226
227 return key;
228 }
229
230 return nullptr;
231}
232
233static bool can_draw_retiming(const TimelineDrawContext *timeline_ctx,
234 const StripDrawContext &strip_ctx)
235{
236 if (timeline_ctx->ed == nullptr) {
237 return false;
238 }
239
240 if (!retiming_keys_can_be_displayed(timeline_ctx->sseq)) {
241 return false;
242 }
243
244 if (!SEQ_retiming_is_allowed(strip_ctx.seq)) {
245 return false;
246 }
247
248 if (!strip_ctx.can_draw_retiming_overlay) {
249 return false;
250 }
251
252 return true;
253}
254
255/* -------------------------------------------------------------------- */
259static void retime_key_draw(const TimelineDrawContext *timeline_ctx,
260 const StripDrawContext &strip_ctx,
261 const SeqRetimingKey *key,
262 const KeyframeShaderBindings &sh_bindings)
263{
264 const Scene *scene = timeline_ctx->scene;
265 const View2D *v2d = timeline_ctx->v2d;
266 Sequence *seq = strip_ctx.seq;
267
268 const float key_x = key_x_get(scene, seq, key);
269 const rctf strip_box = strip_box_get(scene, v2d, seq);
270 if (!BLI_rctf_isect_x(&strip_box, UI_view2d_view_to_region_x(v2d, key_x))) {
271 return; /* Key out of the strip bounds. */
272 }
273
276 key_type = BEZT_KEYTYPE_BREAKDOWN;
277 }
279 key_type = BEZT_KEYTYPE_MOVEHOLD;
280 }
281
282 const bool is_selected = timeline_ctx->retiming_selection.contains(
283 const_cast<SeqRetimingKey *>(key));
284 const int size = KEY_SIZE;
285 const float bottom = KEY_CENTER;
286
287 /* Ensure, that key is always inside of strip. */
288 const float right_pos_max = UI_view2d_view_to_region_x(v2d, strip_ctx.right_handle) - (size / 2);
289 const float left_pos_min = UI_view2d_view_to_region_x(v2d, strip_ctx.left_handle) + (size / 2);
290 float key_position = UI_view2d_view_to_region_x(v2d, key_x);
291 CLAMP(key_position, left_pos_min, right_pos_max);
292 const float alpha = SEQ_retiming_data_is_editable(seq) ? 1.0f : 0.3f;
293
294 draw_keyframe_shape(key_position,
295 bottom,
296 size,
297 is_selected && SEQ_retiming_data_is_editable(seq),
298 key_type,
300 alpha,
301 &sh_bindings,
302 0,
303 0);
304}
305
307 const StripDrawContext &strip_ctx)
308{
309 if (!can_draw_retiming(timeline_ctx, strip_ctx) || SEQ_retiming_keys_count(strip_ctx.seq) == 0) {
310 return;
311 }
312
313 const Sequence *seq = strip_ctx.seq;
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(seq)) {
320 if (key_x_get(scene, seq, &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, seq, &key));
325 float prev_key_position = UI_view2d_view_to_region_x(v2d, key_x_get(scene, seq, &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 Sequence *seq, int key_x)
361{
362 int sound_offset = SEQ_time_get_rounded_sound_offset(scene, seq);
363 SeqRetimingKey fake_key = {0};
364 fake_key.strip_frame_index = (key_x - SEQ_time_start_frame_get(seq) - sound_offset) *
366 fake_key.flag = 0;
367 return fake_key;
368}
369
370/* If there are no keys, draw fake keys and create real key when they are selected. */
371/* TODO: would be nice to draw continuity between fake keys. */
372static bool fake_keys_draw(const TimelineDrawContext *timeline_ctx,
373 const StripDrawContext &strip_ctx,
374 const KeyframeShaderBindings &sh_bindings)
375{
376 const Sequence *seq = strip_ctx.seq;
377 const Scene *scene = timeline_ctx->scene;
378
380 return false;
381 }
382
383 const int left_key_frame = left_fake_key_frame_get(timeline_ctx->C, seq);
384 if (SEQ_retiming_key_get_by_timeline_frame(scene, seq, left_key_frame) == nullptr) {
385 SeqRetimingKey fake_key = fake_retiming_key_init(scene, seq, left_key_frame);
386 retime_key_draw(timeline_ctx, strip_ctx, &fake_key, sh_bindings);
387 }
388
389 int right_key_frame = right_fake_key_frame_get(timeline_ctx->C, seq);
390 if (SEQ_retiming_key_get_by_timeline_frame(scene, seq, right_key_frame) == nullptr) {
391 /* `key_x_get()` compensates 1 frame offset of last key, however this can not
392 * be conveyed via `fake_key` alone. Therefore the same offset must be emulated. */
393 if (strip_ctx.right_handle >= SEQ_time_content_end_frame_get(scene, seq)) {
394 right_key_frame += 1;
395 }
396 SeqRetimingKey fake_key = fake_retiming_key_init(scene, seq, right_key_frame);
397 retime_key_draw(timeline_ctx, strip_ctx, &fake_key, sh_bindings);
398 }
399 return true;
400}
401
404{
405 if (strips.is_empty()) {
406 return;
407 }
408 if (timeline_ctx->ed == nullptr || !retiming_keys_can_be_displayed(timeline_ctx->sseq)) {
409 return;
410 }
411
413 wmOrtho2_region_pixelspace(timeline_ctx->region);
414
415 const View2D *v2d = timeline_ctx->v2d;
416
418 KeyframeShaderBindings sh_bindings;
421 sh_bindings.color_id = GPU_vertformat_attr_add(
424 format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
426
429 immUniform1f("outline_scale", 1.0f);
430 immUniform2f("ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
431
432 constexpr int MAX_KEYS_IN_BATCH = 1024;
433 int point_counter = 0;
434 immBeginAtMost(GPU_PRIM_POINTS, MAX_KEYS_IN_BATCH);
435
436 for (const StripDrawContext &strip_ctx : strips) {
437 if (!can_draw_retiming(timeline_ctx, strip_ctx)) {
438 continue;
439 }
440 if (fake_keys_draw(timeline_ctx, strip_ctx, sh_bindings)) {
441 point_counter += 2;
442 }
443
444 for (const SeqRetimingKey &key : SEQ_retiming_keys_get(strip_ctx.seq)) {
445 retime_key_draw(timeline_ctx, strip_ctx, &key, sh_bindings);
446 point_counter++;
447
448 /* Next key plus possible two fake keys for next sequence would need at
449 * most 3 points, so restart the batch if we're close to that. */
450 if (point_counter + 3 >= MAX_KEYS_IN_BATCH) {
451 immEnd();
452 immBeginAtMost(GPU_PRIM_POINTS, MAX_KEYS_IN_BATCH);
453 point_counter = 0;
454 }
455 }
456 }
457
458 immEnd();
461
463}
464
467/* -------------------------------------------------------------------- */
471static size_t label_str_get(const Sequence *seq,
472 const SeqRetimingKey *key,
473 char *r_label_str,
474 const size_t label_str_maxncpy)
475{
476 const SeqRetimingKey *next_key = key + 1;
478 const float prev_speed = SEQ_retiming_key_speed_get(seq, key);
479 const float next_speed = SEQ_retiming_key_speed_get(seq, next_key + 1);
480 return BLI_snprintf_rlen(r_label_str,
481 label_str_maxncpy,
482 "%d%% - %d%%",
483 round_fl_to_int(prev_speed * 100.0f),
484 round_fl_to_int(next_speed * 100.0f));
485 }
486 const float speed = SEQ_retiming_key_speed_get(seq, next_key);
487 return BLI_snprintf_rlen(
488 r_label_str, label_str_maxncpy, "%d%%", round_fl_to_int(speed * 100.0f));
489}
490
491static bool label_rect_get(const TimelineDrawContext *timeline_ctx,
492 const StripDrawContext &strip_ctx,
493 const SeqRetimingKey *key,
494 const char *label_str,
495 const size_t label_len,
496 rctf *rect)
497{
498 const bContext *C = timeline_ctx->C;
499 const Scene *scene = timeline_ctx->scene;
500 const SeqRetimingKey *next_key = key + 1;
501 const float width = pixels_to_view_width(C, BLF_width(BLF_default(), label_str, label_len));
502 const float height = pixels_to_view_height(C, BLF_height(BLF_default(), label_str, label_len));
503 const float xmin = max_ff(strip_ctx.left_handle, key_x_get(scene, strip_ctx.seq, key));
504 const float xmax = min_ff(strip_ctx.right_handle, key_x_get(scene, strip_ctx.seq, next_key));
505
506 rect->xmin = (xmin + xmax - width) / 2;
507 rect->xmax = rect->xmin + width;
508 rect->ymin = strip_y_rescale(strip_ctx.seq, 0) + pixels_to_view_height(C, 5);
509 rect->ymax = rect->ymin + height;
510
511 return width < xmax - xmin - pixels_to_view_width(C, KEY_SIZE);
512}
513
514static void retime_speed_text_draw(const TimelineDrawContext *timeline_ctx,
515 const StripDrawContext &strip_ctx,
516 const SeqRetimingKey *key)
517{
518 const Sequence *seq = strip_ctx.seq;
519 const Scene *scene = timeline_ctx->scene;
520
521 if (SEQ_retiming_is_last_key(seq, key)) {
522 return;
523 }
524
525 const SeqRetimingKey *next_key = key + 1;
526 if (key_x_get(scene, seq, next_key) < strip_ctx.left_handle ||
527 key_x_get(scene, seq, key) > strip_ctx.right_handle)
528 {
529 return; /* Label out of strip bounds. */
530 }
531
532 char label_str[40];
533 rctf label_rect;
534 size_t label_len = label_str_get(seq, key, label_str, sizeof(label_str));
535
536 if (!label_rect_get(timeline_ctx, strip_ctx, key, label_str, label_len, &label_rect)) {
537 return; /* Not enough space to draw the label. */
538 }
539
540 uchar col[4] = {255, 255, 255, 255};
541 if ((seq->flag & SELECT) == 0) {
542 memset(col, 0, sizeof(col));
543 col[3] = 255;
544 }
545
547 timeline_ctx->v2d, label_rect.xmin, label_rect.ymin, label_str, label_len, col);
548}
549
551 const StripDrawContext &strip_ctx)
552{
553 if (!can_draw_retiming(timeline_ctx, strip_ctx)) {
554 return;
555 }
556
557 for (const SeqRetimingKey &key : SEQ_retiming_keys_get(strip_ctx.seq)) {
558 retime_speed_text_draw(timeline_ctx, strip_ctx, &key);
559 }
560
561 UI_view2d_view_ortho(timeline_ctx->v2d);
562}
563
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:815
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:791
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.c:93
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:193
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:189
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 SEQ_STRIP_OFSBOTTOM
#define SEQ_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:175
@ GPU_FETCH_FLOAT
@ GPU_FETCH_INT_TO_FLOAT_UNIT
@ GPU_FETCH_INT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
@ GPU_COMP_U32
@ GPU_COMP_U8
Read Guarded memory(de)allocation.
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:2077
float UI_view2d_view_to_region_y(const View2D *v2d, float y)
Definition view2d.cc:1691
void UI_view2d_view_ortho(const View2D *v2d)
Definition view2d.cc:1091
View2D * UI_view2d_fromcontext(const bContext *C)
Definition view2d.cc:1850
float UI_view2d_view_to_region_x(const View2D *v2d, float x)
Definition view2d.cc:1686
void add_quad(float x1, float y1, float x2, float y2, const uchar color[4])
bool contains(const Key &key) const
Definition BLI_map.hh:329
constexpr bool is_empty() const
Definition BLI_span.hh:261
#define SELECT
#define fabsf(x)
uint col
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)
float distance(float a, float b)
blender::Vector< Sequence * > sequencer_visible_strips_get(const bContext *C)
SeqRetimingKey * retiming_mouseover_key_get(const bContext *C, const int mval[2], Sequence **r_seq)
static float pixels_to_view_width(const bContext *C, const float width)
void sequencer_retiming_draw_continuity(const TimelineDrawContext *timeline_ctx, const StripDrawContext &strip_ctx)
static void retime_speed_text_draw(const TimelineDrawContext *timeline_ctx, const StripDrawContext &strip_ctx, const SeqRetimingKey *key)
static rctf strip_box_get(const Scene *scene, const View2D *v2d, const Sequence *seq)
static bool fake_keys_draw(const TimelineDrawContext *timeline_ctx, const StripDrawContext &strip_ctx, const KeyframeShaderBindings &sh_bindings)
#define KEY_CENTER
#define KEY_SIZE
int left_fake_key_frame_get(const bContext *C, const Sequence *seq)
static bool retiming_fake_key_frame_clicked(const bContext *C, const Sequence *seq, const int mval[2], int &r_frame)
SeqRetimingKey * try_to_realize_fake_keys(const bContext *C, Sequence *seq, const int mval[2])
static float strip_start_screenspace_get(const Scene *scene, const View2D *v2d, const Sequence *seq)
void sequencer_retiming_keys_draw(const TimelineDrawContext *timeline_ctx, blender::Span< StripDrawContext > strips)
static float strip_y_rescale(const Sequence *seq, const float y_value)
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)
void sequencer_retiming_speed_draw(const TimelineDrawContext *timeline_ctx, const StripDrawContext &strip_ctx)
static SeqRetimingKey * mouse_over_key_get_from_strip(const bContext *C, const Sequence *seq, const int mval[2])
static SeqRetimingKey fake_retiming_key_init(const Scene *scene, const Sequence *seq, int key_x)
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 void retime_key_draw(const TimelineDrawContext *timeline_ctx, const StripDrawContext &strip_ctx, const SeqRetimingKey *key, const KeyframeShaderBindings &sh_bindings)
static size_t label_str_get(const Sequence *seq, const SeqRetimingKey *key, char *r_label_str, const size_t label_str_maxncpy)
void realize_fake_keys(const Scene *scene, Sequence *seq)
int right_fake_key_frame_get(const bContext *C, const Sequence *seq)
bool retiming_keys_can_be_displayed(const SpaceSeq *sseq)
static float strip_end_screenspace_get(const Scene *scene, const View2D *v2d, const Sequence *seq)
static float key_x_get(const Scene *scene, const Sequence *seq, const SeqRetimingKey *key)
#define RETIME_KEY_MOUSEOVER_THRESHOLD
rctf seq_retiming_keys_box_get(const Scene *scene, const View2D *v2d, const Sequence *seq)
MutableSpan< SeqRetimingKey > SEQ_retiming_keys_get(const Sequence *seq)
int SEQ_retiming_keys_count(const Sequence *seq)
bool SEQ_retiming_data_is_editable(const Sequence *seq)
bool SEQ_retiming_is_active(const Sequence *seq)
bool SEQ_retiming_key_is_freeze_frame(const SeqRetimingKey *key)
bool SEQ_retiming_key_is_transition_type(const SeqRetimingKey *key)
bool SEQ_retiming_is_allowed(const Sequence *seq)
int SEQ_retiming_key_timeline_frame_get(const Scene *scene, const Sequence *seq, const SeqRetimingKey *key)
SeqRetimingKey * SEQ_retiming_key_get_by_timeline_frame(const Scene *scene, const Sequence *seq, const int timeline_frame)
float SEQ_retiming_key_speed_get(const Sequence *seq, const SeqRetimingKey *key)
void SEQ_retiming_data_ensure(Sequence *seq)
bool SEQ_retiming_is_last_key(const Sequence *seq, const SeqRetimingKey *key)
bool SEQ_retiming_key_is_transition_start(const SeqRetimingKey *key)
SeqRetimingKey * SEQ_retiming_add_key(const Scene *scene, Sequence *seq, const int timeline_frame)
int SEQ_time_get_rounded_sound_offset(const Scene *scene, const Sequence *seq)
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)
float SEQ_time_media_playback_rate_factor_get(const Scene *scene, const Sequence *seq)
Definition strip_time.cc:38
int SEQ_time_right_handle_frame_get(const Scene *scene, const Sequence *seq)
struct SequencerTimelineOverlay timeline_overlay
blender::Map< SeqRetimingKey *, Sequence * > retiming_selection
float xmax
float xmin
float ymax
float ymin
void wmOrtho2_region_pixelspace(const ARegion *region)