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
8
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
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)) {
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);
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/* -------------------------------------------------------------------- */
258
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
466
467/* -------------------------------------------------------------------- */
470
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.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a color
#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: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
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
bool contains(const Key &key) const
Definition BLI_map.hh:329
void add_quad(float x1, float y1, float x2, float y2, const uchar color[4])
constexpr bool is_empty() const
Definition BLI_span.hh:261
#define SELECT
#define fabsf(x)
uint col
uint top
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)
bool retiming_keys_can_be_displayed(const SpaceSeq *sseq)
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)