Blender V5.0
sequencer_drag_drop.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "MEM_guardedalloc.h"
10
11#include "DNA_scene_types.h"
12#include "DNA_sound_types.h"
13
14#include "BLI_math_base.h"
15#include "BLI_path_utils.hh"
16#include "BLI_string.h"
17#include "BLI_string_ref.hh"
18#include "BLI_string_utf8.h"
19#include "BLI_string_utils.hh"
20
21#include "BKE_context.hh"
22#include "BKE_file_handler.hh"
23#include "BKE_image.hh"
24#include "BKE_main.hh"
25
26#include "SEQ_channels.hh"
27#include "SEQ_iterator.hh"
28#include "SEQ_sequencer.hh"
29#include "SEQ_transform.hh"
30
31#include "UI_resources.hh"
32#include "UI_view2d.hh"
33
34#include "GPU_matrix.hh"
35#include "GPU_state.hh"
36
37#include "ED_screen.hh"
38#include "ED_transform.hh"
39
40#include "IMB_imbuf_types.hh"
41
42#include "MOV_read.hh"
43
44#include "WM_api.hh"
45#include "WM_types.hh"
46
47/* For querying audio files. */
48#ifdef WITH_AUDASPACE
49# include "BKE_sound.h"
50# include <AUD_Sound.h>
51# include <AUD_Special.h>
52#endif
53
54/* Own include. */
55#include "sequencer_intern.hh"
57
58namespace blender::ed::vse {
59
65 bool only_audio = false;
66 bool in_use = false;
67 bool has_read_mouse_pos = false;
71 uint8_t type;
72};
73
74/* The current drag and drop API doesn't allow us to easily pass along the
75 * required custom data to all callbacks that need it. Especially when
76 * preloading data on drag start.
77 * Therefore we will for now use a global variable for this.
78 */
80
81static void generic_poll_operations(const wmEvent *event, uint8_t type)
82{
83 g_drop_coords.type = type;
84 /* We purposely ignore the snapping tool setting here as currently other drag&drop operators only
85 * snaps when holding down Ctrl. */
86 g_drop_coords.use_snapping = event->modifier & KM_CTRL;
87}
88
89/* While drag-and-drop in the sequencer, the internal drop-box implementation allows to have a drop
90 * preview of the file dragged. This checks when drag-and-drop is done with a single file, and when
91 * only a expected `file_handler` can be used, so internal drop-box can be used instead of the
92 * `file_handler`. */
94 wmDrag *drag,
95 blender::StringRef file_handler)
96{
97 const auto paths = WM_drag_get_paths(drag);
98 auto file_handlers = blender::bke::file_handlers_poll_file_drop(C, paths);
99 return paths.size() == 1 && file_handlers.size() == 1 &&
100 file_handler == file_handlers[0]->idname;
101}
102
103static bool image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
104{
105 if (drag->type == WM_DRAG_PATH) {
107 if (file_type == FILE_TYPE_IMAGE &&
108 test_single_file_handler_poll(C, drag, "SEQUENCER_FH_image_strip"))
109 {
111 return true;
112 }
113 }
114
115 if (WM_drag_is_ID_type(drag, ID_IM)) {
117 return true;
118 }
119
120 return false;
121}
122
123static bool is_movie(wmDrag *drag)
124{
125 if (drag->type == WM_DRAG_PATH) {
127 if (file_type == FILE_TYPE_MOVIE) {
128 return true;
129 }
130 }
131 if (WM_drag_is_ID_type(drag, ID_MC)) {
132 return true;
133 }
134 return false;
135}
136
137static bool movie_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
138{
139 if (is_movie(drag) && (drag->type != WM_DRAG_PATH ||
140 test_single_file_handler_poll(C, drag, "SEQUENCER_FH_movie_strip")))
141 {
143 return true;
144 }
145
146 return false;
147}
148
149static bool is_sound(wmDrag *drag)
150{
151 if (drag->type == WM_DRAG_PATH) {
153 if (file_type == FILE_TYPE_SOUND) {
154 return true;
155 }
156 }
157 if (WM_drag_is_ID_type(drag, ID_SO)) {
158 return true;
159 }
160 return false;
161}
162
163static bool sound_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
164{
165 if (is_sound(drag) && (drag->type != WM_DRAG_PATH ||
166 test_single_file_handler_poll(C, drag, "SEQUENCER_FH_sound_strip")))
167 {
169 return true;
170 }
171
172 return false;
173}
174
175static float update_overlay_strip_position_data(bContext *C, const int mval[2])
176{
177 SeqDropCoords *coords = &g_drop_coords;
178 ARegion *region = CTX_wm_region(C);
180 View2D *v2d = &region->v2d;
181
182 /* Update the position were we would place the strip if we complete the drag and drop action.
183 */
184 UI_view2d_region_to_view(v2d, mval[0], mval[1], &coords->start_frame, &coords->channel);
185 coords->start_frame = roundf(coords->start_frame);
186 if (coords->channel < 1.0f) {
187 coords->channel = 1;
188 }
189
190 float start_frame = coords->start_frame;
191 float end_frame;
192 float strip_len;
193
194 if (coords->playback_rate != 0.0f) {
195 float scene_playback_rate = float(scene->r.frs_sec) / scene->r.frs_sec_base;
196 strip_len = coords->strip_len / (coords->playback_rate / scene_playback_rate);
197 }
198 else if (coords->only_audio) {
199 float scene_playback_rate = float(scene->r.frs_sec) / scene->r.frs_sec_base;
200 strip_len = coords->audio_length * scene_playback_rate;
201 }
202 else {
203 strip_len = coords->strip_len;
204 }
205
206 end_frame = coords->start_frame + strip_len;
207
208 if (coords->use_snapping) {
209 /* Do snapping via the existing transform code. */
210 int snap_delta;
211 float snap_frame;
212 bool valid_snap;
213
215 scene, region, start_frame, end_frame, &snap_delta, &snap_frame);
216
217 if (valid_snap) {
218 /* We snapped onto something! */
219 start_frame += snap_delta;
220 coords->start_frame = start_frame;
221 end_frame = start_frame + strip_len;
222 coords->snap_point_x = snap_frame;
223 }
224 else {
225 /* Nothing was snapped to, disable snap drawing. */
226 coords->use_snapping = false;
227 }
228 }
229
230 /* Check if there is a strip that would intersect with the new strip(s). */
231 coords->is_intersecting = false;
232 Strip dummy_strip{};
233 seq::strip_channel_set(&dummy_strip, coords->channel);
234 dummy_strip.start = coords->start_frame;
235 dummy_strip.len = coords->strip_len;
236 dummy_strip.speed_factor = 1.0f;
237 dummy_strip.media_playback_rate = coords->playback_rate;
238 dummy_strip.flag = SEQ_AUTO_PLAYBACK_RATE;
240
241 for (int i = 0; i < coords->channel_len && !coords->is_intersecting; i++) {
243 scene, ed->current_strips(), &dummy_strip);
244 seq::strip_channel_set(&dummy_strip, dummy_strip.channel + 1);
245 }
246
247 return strip_len;
248}
249
250static void sequencer_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop)
251{
252 if (g_drop_coords.in_use) {
253 if (!g_drop_coords.has_read_mouse_pos) {
254 /* We didn't read the mouse position, so we need to do it manually here. */
255 int xy[2];
256 wmWindow *win = CTX_wm_window(C);
257 xy[0] = win->eventstate->xy[0];
258 xy[1] = win->eventstate->xy[1];
259
260 ARegion *region = CTX_wm_region(C);
261 int mval[2];
262 /* Convert mouse coordinates to region local coordinates. */
263 mval[0] = xy[0] - region->winrct.xmin;
264 mval[1] = xy[1] - region->winrct.ymin;
265
267 }
268
269 RNA_int_set(drop->ptr, "frame_start", g_drop_coords.start_frame);
270 RNA_int_set(drop->ptr, "channel", g_drop_coords.channel);
271 RNA_boolean_set(drop->ptr, "overlap_shuffle_override", true);
272 RNA_boolean_set(drop->ptr, "skip_locked_or_muted_channels", false);
273 }
274 else {
275 /* We are dropped inside the preview region. Put the strip on top of the
276 * current displayed frame. */
281 SpaceSeq *sseq = CTX_wm_space_seq(C);
282
284 scene, channels, seqbase, scene->r.cfra, sseq->chanshown);
285
286 /* Get the top most strip channel that is in view. */
287 int max_channel = -1;
288 for (Strip *strip : strips) {
289 max_channel = max_ii(strip->channel, max_channel);
290 }
291
292 if (max_channel != -1) {
293 RNA_int_set(drop->ptr, "channel", max_channel);
294 }
295 }
296
298 /* ID dropped. */
299 if (id != nullptr) {
300 const ID_Type id_type = GS(id->name);
301 if (id_type == ID_IM) {
302 Image *ima = (Image *)id;
303 PointerRNA itemptr;
304 char dir[FILE_MAX], file[FILE_MAX];
305 BLI_path_split_dir_file(ima->filepath, dir, sizeof(dir), file, sizeof(file));
306 RNA_string_set(drop->ptr, "directory", dir);
307 RNA_collection_clear(drop->ptr, "files");
308 RNA_collection_add(drop->ptr, "files", &itemptr);
309 RNA_string_set(&itemptr, "name", file);
310 }
311 else if (id_type == ID_MC) {
312 MovieClip *clip = (MovieClip *)id;
313 RNA_string_set(drop->ptr, "filepath", clip->filepath);
314 RNA_struct_property_unset(drop->ptr, "name");
315 }
316 else if (id_type == ID_SO) {
317 bSound *sound = (bSound *)id;
318 RNA_string_set(drop->ptr, "filepath", sound->filepath);
319 RNA_struct_property_unset(drop->ptr, "name");
320 }
321
322 return;
323 }
324
325 const char *path = WM_drag_get_single_path(drag);
326 /* Path dropped. */
327 if (path) {
328 if (RNA_struct_find_property(drop->ptr, "filepath")) {
329 RNA_string_set(drop->ptr, "filepath", path);
330 }
331 if (RNA_struct_find_property(drop->ptr, "directory")) {
332 PointerRNA itemptr;
333 char dir[FILE_MAX], file[FILE_MAX];
334
335 BLI_path_split_dir_file(path, dir, sizeof(dir), file, sizeof(file));
336
337 RNA_string_set(drop->ptr, "directory", dir);
338
339 RNA_collection_clear(drop->ptr, "files");
340 RNA_collection_add(drop->ptr, "files", &itemptr);
341 RNA_string_set(&itemptr, "name", file);
342 }
343 }
344}
345
346static void get_drag_path(const bContext *C, wmDrag *drag, char r_path[FILE_MAX])
347{
349 /* ID dropped. */
350 if (id != nullptr) {
351 const ID_Type id_type = GS(id->name);
352 if (id_type == ID_IM) {
353 Image *ima = (Image *)id;
354 BLI_strncpy(r_path, ima->filepath, FILE_MAX);
355 }
356 else if (id_type == ID_MC) {
357 MovieClip *clip = (MovieClip *)id;
358 BLI_strncpy(r_path, clip->filepath, FILE_MAX);
359 }
360 else if (id_type == ID_SO) {
361 bSound *sound = (bSound *)id;
362 BLI_strncpy(r_path, sound->filepath, FILE_MAX);
363 }
365 }
366 else {
368 }
369}
370
371static void draw_strip_in_view(bContext *C, wmWindow * /*win*/, wmDrag *drag, const int xy[2])
372{
373 SeqDropCoords *coords = &g_drop_coords;
374 if (!coords->in_use) {
375 return;
376 }
377
378 ARegion *region = CTX_wm_region(C);
379 int mval[2];
380 /* Convert mouse coordinates to region local coordinates. */
381 mval[0] = xy[0] - region->winrct.xmin;
382 mval[1] = xy[1] - region->winrct.ymin;
383
384 float strip_len = update_overlay_strip_position_data(C, mval);
385
388
389 /* Sometimes the active theme is not the sequencer theme, e.g. when an operator invokes the
390 * file browser. This makes sure we get the right color values for the theme. */
391 bThemeState theme_state;
392 UI_Theme_Store(&theme_state);
394
395 if (coords->use_snapping) {
397 }
398
399 /* Init GPU drawing. */
401
402 /* Draw strips. The code here is taken from sequencer_draw. */
403 float x1 = coords->start_frame;
404 float x2 = coords->start_frame + floorf(strip_len);
405 uchar strip_color[4];
406 strip_color[3] = 255;
407 uchar text_color[4] = {255, 255, 255, 255};
408 float pixelx = BLI_rctf_size_x(&region->v2d.cur) / (BLI_rcti_size_x(&region->v2d.mask) + 1);
409 float pixely = BLI_rctf_size_y(&region->v2d.cur) / (BLI_rcti_size_y(&region->v2d.mask) + 1);
410
411 StripsDrawBatch batch(&region->v2d);
412
413 for (int i = 0; i < coords->channel_len; i++) {
414 float y1 = floorf(coords->channel) + i + STRIP_OFSBOTTOM;
415 float y2 = floorf(coords->channel) + i + STRIP_OFSTOP;
416
417 if (coords->type == TH_SEQ_MOVIE && i == 0 && coords->channel_len > 1) {
418 /* Assume only video strips occupies two channels.
419 * One for video and the other for audio.
420 * The audio channel is added first.
421 */
423 }
424 else {
425 UI_GetThemeColor3ubv(coords->type, strip_color);
426 }
427
428 SeqStripDrawData &data = batch.add_strip(x1, x2, y2, y1, y2, x1, x2, 0, true);
430 data.col_background = color_pack(strip_color);
431
432 if (coords->is_intersecting) {
433 strip_color[0] = 255;
434 strip_color[1] = strip_color[2] = 33;
435 }
436 else {
437 if (coords->channel_len - 1 == i) {
438 text_color[0] = text_color[1] = text_color[2] = 255;
440 data.flags |= GPU_SEQ_FLAG_ACTIVE;
441 }
442 else {
443 text_color[0] = text_color[1] = text_color[2] = 10;
445 }
446 }
447 strip_color[3] = 204;
448 data.col_outline = color_pack(strip_color);
449
450 /* Taken from strip_handle_draw_size_get(). */
451 const float handle_size = pixelx * (5.0f * U.pixelsize);
452
453 /* Calculate height needed for drawing text on strip. */
454 float text_margin_y = y2 - min_ff(0.40f, 20 * UI_SCALE_FAC * pixely);
455 float text_margin_x = 2.0f * handle_size;
456
457 rctf rect;
458 rect.xmin = x1 + text_margin_x;
459 rect.ymin = text_margin_y;
460 rect.xmax = x2 - text_margin_x;
461 rect.ymax = y2;
462
463 if (rect.xmax <= rect.xmin) {
464 /* Exit early and skip text drawing if the strip doesn't have any space to put the text
465 * into.
466 */
467 break;
468 }
469
470 SpaceSeq *sseq = CTX_wm_space_seq(C);
471 const char *text_sep = " | ";
472 const char *text_array[5];
473 char text_display[FILE_MAX];
474 char filename[FILE_MAX];
475 char path[FILE_MAX];
476 char strip_duration_text[16];
477 int len_text_arr = 0;
478
479 get_drag_path(C, drag, path);
480
482 BLI_path_split_file_part(path, filename, FILE_MAX);
483 text_array[len_text_arr++] = filename;
484 }
485
487 Main *bmain = CTX_data_main(C);
489 text_array[len_text_arr++] = text_sep;
490 text_array[len_text_arr++] = path;
491 }
492
494 SNPRINTF_UTF8(strip_duration_text, "%d", int(x2 - x1));
495 text_array[len_text_arr++] = text_sep;
496 text_array[len_text_arr++] = strip_duration_text;
497 }
498
499 BLI_assert(len_text_arr <= ARRAY_SIZE(text_array));
500
501 const size_t text_display_len = BLI_string_join_array(
502 text_display, FILE_MAX, text_array, len_text_arr);
503
505 &region->v2d, &rect, text_display, text_display_len, text_color);
506 }
507 batch.flush_batch();
508
509 /* Clean after drawing up. */
510 UI_Theme_Restore(&theme_state);
513
515}
516
518{
519 SeqDropCoords *coords = static_cast<SeqDropCoords *>(drop->draw_data);
520 if (coords && coords->in_use) {
521 return true;
522 }
523
524 coords = &g_drop_coords;
525 drop->draw_data = static_cast<void *>(&g_drop_coords);
526 coords->in_use = true;
527
528 return false;
529}
530
538};
539
540static void prefetch_data_fn(void *custom_data, wmJobWorkerStatus * /*worker_status*/)
541{
542 DropJobData *job_data = (DropJobData *)custom_data;
543
544 if (job_data->only_audio) {
545#ifdef WITH_AUDASPACE
546 /* Get the sound file length */
547 AUD_Sound *sound = AUD_Sound_file(job_data->path);
548 if (sound != nullptr) {
549
550 AUD_SoundInfo info = AUD_getInfo(sound);
551 if ((eSoundChannels)info.specs.channels != SOUND_CHANNELS_INVALID) {
552 g_drop_coords.audio_length = info.length;
553 }
554 /* The playback rate is defined by the scene. This will be computed later in
555 * #update_overlay_strip_position_data, when we know the scene from the context. So set it to
556 * 0 for now. */
557 g_drop_coords.playback_rate = 0.0f;
558 AUD_Sound_free(sound);
559 return;
560 }
561#endif
562 }
563
564 /* The movie reader is not used to access pixel data here, so avoid internal colorspace
565 * conversions that ensures typical color pipeline in Blender as they might be expensive. */
566 char colorspace[/*MAX_COLORSPACE_NAME*/ 64] = "\0";
567 MovieReader *anim = openanim(job_data->path, IB_byte_data, 0, true, colorspace);
568
569 if (anim != nullptr) {
571 g_drop_coords.playback_rate = MOV_get_fps(anim);
572 MOV_close(anim);
573#ifdef WITH_AUDASPACE
574 /* Try to load sound and see if the video has a sound channel. */
575 AUD_Sound *sound = AUD_Sound_file(job_data->path);
576 if (sound != nullptr) {
577
578 AUD_SoundInfo info = AUD_getInfo(sound);
579 if ((eSoundChannels)info.specs.channels != SOUND_CHANNELS_INVALID) {
580 g_drop_coords.channel_len = 2;
581 }
582 AUD_Sound_free(sound);
583 }
584#endif
585 }
586}
587
588static void free_prefetch_data_fn(void *custom_data)
589{
590 DropJobData *job_data = (DropJobData *)custom_data;
591 MEM_freeN(job_data);
592}
593
594static void start_audio_video_job(bContext *C, wmDrag *drag, bool only_audio)
595{
596 g_drop_coords.strip_len = 0;
597 g_drop_coords.channel_len = 1;
598
600
601 wmJob *wm_job = WM_jobs_get(wm,
602 nullptr,
603 nullptr,
604 "Loading previews...",
605 eWM_JobFlag(0),
607
608 DropJobData *job_data = MEM_mallocN<DropJobData>("SeqDragDropPreviewData");
609 get_drag_path(C, drag, job_data->path);
610
611 job_data->only_audio = only_audio;
612 g_drop_coords.only_audio = only_audio;
613
615 WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW);
616 WM_jobs_callbacks(wm_job, prefetch_data_fn, nullptr, nullptr, nullptr);
617
618 WM_jobs_start(wm, wm_job);
619}
620
621static void video_prefetch(bContext *C, wmDrag *drag)
622{
623 if (is_movie(drag)) {
624 start_audio_video_job(C, drag, false);
625 }
626}
627
628static void audio_prefetch(bContext *C, wmDrag *drag)
629{
630 if (is_sound(drag)) {
631 start_audio_video_job(C, drag, true);
632 }
633}
634
635static void movie_drop_on_enter(wmDropBox *drop, wmDrag * /*drag*/)
636{
637 if (generic_drop_draw_handling(drop)) {
638 return;
639 }
640}
641
642static void sound_drop_on_enter(wmDropBox *drop, wmDrag * /*drag*/)
643{
644 if (generic_drop_draw_handling(drop)) {
645 return;
646 }
647}
648
649static void image_drop_on_enter(wmDropBox *drop, wmDrag * /*drag*/)
650{
651 if (generic_drop_draw_handling(drop)) {
652 return;
653 }
654
655 SeqDropCoords *coords = static_cast<SeqDropCoords *>(drop->draw_data);
657 coords->channel_len = 1;
658}
659
660static void sequencer_drop_on_exit(wmDropBox *drop, wmDrag * /*drag*/)
661{
662 SeqDropCoords *coords = static_cast<SeqDropCoords *>(drop->draw_data);
663 if (coords) {
664 coords->in_use = false;
665 coords->has_read_mouse_pos = false;
666 drop->draw_data = nullptr;
667 }
668}
669
670static void nop_draw_droptip_fn(bContext * /*C*/,
671 wmWindow * /*win*/,
672 wmDrag * /*drag*/,
673 const int /*xy*/[2])
674{
675 /* Do nothing in here.
676 * This is to prevent the default drag and drop mouse overlay to be drawn.
677 */
678}
679
680/* This region dropbox definition. */
682{
683 wmDropBox *drop;
684 drop = WM_dropbox_add(
685 lb, "SEQUENCER_OT_image_strip_add", image_drop_poll, sequencer_drop_copy, nullptr, nullptr);
690
692
693 drop = WM_dropbox_add(
694 lb, "SEQUENCER_OT_movie_strip_add", movie_drop_poll, sequencer_drop_copy, nullptr, nullptr);
699
701
702 drop = WM_dropbox_add(
703 lb, "SEQUENCER_OT_sound_strip_add", sound_drop_poll, sequencer_drop_copy, nullptr, nullptr);
708}
709
710static bool image_drop_preview_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*event*/)
711{
712 if (drag->type == WM_DRAG_PATH) {
714 if (file_type == FILE_TYPE_IMAGE) {
715 return true;
716 }
717 }
718
719 return WM_drag_is_ID_type(drag, ID_IM);
720}
721
722static bool movie_drop_preview_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*event*/)
723{
724 if (drag->type == WM_DRAG_PATH) {
726 if (file_type == FILE_TYPE_MOVIE) {
727 return true;
728 }
729 }
730
731 return WM_drag_is_ID_type(drag, ID_MC);
732}
733
734static bool sound_drop_preview_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*event*/)
735{
736 if (drag->type == WM_DRAG_PATH) {
738 if (file_type == FILE_TYPE_SOUND) {
739 return true;
740 }
741 }
742
743 return WM_drag_is_ID_type(drag, ID_SO);
744}
745
747{
749 "SEQUENCER_OT_image_strip_add",
752 nullptr,
753 nullptr);
754
756 "SEQUENCER_OT_movie_strip_add",
759 nullptr,
760 nullptr);
761
763 "SEQUENCER_OT_sound_strip_add",
766 nullptr,
767 nullptr);
768}
769
777
778} // namespace blender::ed::vse
wmWindow * CTX_wm_window(const bContext *C)
SpaceSeq * CTX_wm_space_seq(const bContext *C)
Main * CTX_data_main(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
Scene * CTX_data_sequencer_scene(const bContext *C)
MovieReader * openanim(const char *filepath, int ibuf_flags, int streamindex, bool keep_original_colorspace, char colorspace[IMA_MAX_SPACE])
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:887
eSoundChannels
Definition BKE_sound.h:62
@ SOUND_CHANNELS_INVALID
Definition BKE_sound.h:63
#define BLI_assert(a)
Definition BLI_assert.h:46
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
#define FILE_MAX
void void void BLI_path_split_file_part(const char *filepath, char *file, size_t file_maxncpy) ATTR_NONNULL(1
void BLI_path_split_dir_file(const char *filepath, char *dir, size_t dir_maxncpy, char *file, size_t file_maxncpy) ATTR_NONNULL(1
bool void BLI_path_rel(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1)
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
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition BLI_rect.h:202
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition BLI_rect.h:206
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define SNPRINTF_UTF8(dst, format,...)
size_t BLI_string_join_array(char *result, size_t result_maxncpy, const char *strings[], uint strings_num) ATTR_NONNULL()
unsigned char uchar
#define ARRAY_SIZE(arr)
#define ID_BLEND_PATH_FROM_GLOBAL(_id)
Definition DNA_ID.h:688
ID_Type
@ ID_MC
@ ID_IM
@ ID_SO
@ RGN_TYPE_WINDOW
@ RGN_TYPE_PREVIEW
#define STRIP_OFSBOTTOM
#define STRIP_OFSTOP
@ SEQ_AUTO_PLAYBACK_RATE
eFileSel_File_Types
@ FILE_TYPE_MOVIE
@ FILE_TYPE_SOUND
@ FILE_TYPE_IMAGE
@ SPACE_SEQ
@ SEQ_TIMELINE_SHOW_STRIP_DURATION
@ SEQ_TIMELINE_SHOW_STRIP_SOURCE
@ SEQ_TIMELINE_SHOW_STRIP_NAME
#define UI_SCALE_FAC
void GPU_matrix_push()
void GPU_matrix_pop()
@ GPU_SEQ_FLAG_BACKGROUND
@ GPU_SEQ_FLAG_SELECTED
@ GPU_SEQ_FLAG_BORDER
@ GPU_SEQ_FLAG_ACTIVE
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA_PREMULT
Definition GPU_state.hh:88
void GPU_blend(GPUBlend blend)
Definition gpu_state.cc:42
@ IB_byte_data
Read Guarded memory(de)allocation.
@ IMB_TC_NONE
Definition MOV_enums.hh:46
#define C
Definition RandGen.cpp:29
void UI_Theme_Store(bThemeState *theme_state)
void UI_Theme_Restore(const bThemeState *theme_state)
@ TH_SEQ_SELECTED
@ TH_SEQ_MOVIE
@ TH_SEQ_AUDIO
@ TH_SEQ_ACTIVE
@ TH_SEQ_IMAGE
void UI_GetThemeColor3ubv(int colorid, unsigned char col[3])
void UI_SetTheme(int spacetype, int regionid)
void UI_view2d_text_cache_draw(ARegion *region)
Definition view2d.cc:2142
void UI_view2d_text_cache_add_rectf(View2D *v2d, const rctf *rect_view, const char *str, size_t str_len, const unsigned char col[4])
Definition view2d.cc:2112
void UI_view2d_region_to_view(const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
Definition view2d.cc:1668
@ WM_JOB_TYPE_SEQ_DRAG_DROP_PREVIEW
Definition WM_api.hh:1808
eWM_JobFlag
Definition WM_api.hh:1759
#define NC_WINDOW
Definition WM_types.hh:375
@ KM_CTRL
Definition WM_types.hh:279
@ WM_DRAG_PATH
Definition WM_types.hh:1208
#define U
BMesh const char void * data
nullptr float
#define roundf(x)
#define GS(x)
struct @021025263243242147216143265077100330027142264337::@225245033123204053237120173316075113304004012000 batch
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
void MOV_close(MovieReader *anim)
Definition movie_read.cc:66
int MOV_get_duration_frames(MovieReader *anim, IMB_Timecode_Type tc)
float MOV_get_fps(const MovieReader *anim)
blender::Vector< FileHandlerType * > file_handlers_poll_file_drop(const bContext *C, const blender::Span< std::string > paths)
void sequencer_snap_point(ARegion *region, float snap_point)
bool snap_sequencer_to_closest_strip_calc(Scene *scene, ARegion *region, int frame_1, int frame_2, int *r_snap_distance, float *r_snap_frame)
static void draw_strip_in_view(bContext *C, wmWindow *, wmDrag *drag, const int xy[2])
static void nop_draw_droptip_fn(bContext *, wmWindow *, wmDrag *, const int[2])
static bool image_drop_preview_poll(bContext *, wmDrag *drag, const wmEvent *)
static void sequencer_drop_on_exit(wmDropBox *drop, wmDrag *)
static bool movie_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
static bool is_sound(wmDrag *drag)
uint color_pack(const uchar rgba[4])
static bool sound_drop_preview_poll(bContext *, wmDrag *drag, const wmEvent *)
static bool is_movie(wmDrag *drag)
static void prefetch_data_fn(void *custom_data, wmJobWorkerStatus *)
static bool test_single_file_handler_poll(const bContext *C, wmDrag *drag, blender::StringRef file_handler)
static void video_prefetch(bContext *C, wmDrag *drag)
static void sequencer_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop)
static float update_overlay_strip_position_data(bContext *C, const int mval[2])
static void sequencer_preview_dropboxes_add_to_lb(ListBase *lb)
static void start_audio_video_job(bContext *C, wmDrag *drag, bool only_audio)
static void audio_prefetch(bContext *C, wmDrag *drag)
static SeqDropCoords g_drop_coords
static bool generic_drop_draw_handling(wmDropBox *drop)
static void sequencer_dropboxes_add_to_lb(ListBase *lb)
static void get_drag_path(const bContext *C, wmDrag *drag, char r_path[FILE_MAX])
static bool movie_drop_preview_poll(bContext *, wmDrag *drag, const wmEvent *)
static bool image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
static void sound_drop_on_enter(wmDropBox *drop, wmDrag *)
static void generic_poll_operations(const wmEvent *event, uint8_t type)
static bool sound_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
static void free_prefetch_data_fn(void *custom_data)
static void movie_drop_on_enter(wmDropBox *drop, wmDrag *)
static void image_drop_on_enter(wmDropBox *drop, wmDrag *)
ListBase * channels_displayed_get(const Editing *ed)
Definition channels.cc:28
void strip_channel_set(Strip *strip, int channel)
bool transform_test_overlap(const Scene *scene, Strip *strip1, Strip *strip2)
Editing * editing_ensure(Scene *scene)
Definition sequencer.cc:291
VectorSet< Strip * > query_rendered_strips(const Scene *scene, ListBase *channels, ListBase *seqbase, const int timeline_frame, const int displayed_channel)
Definition iterator.cc:228
ListBase * active_seqbase_get(const Editing *ed)
Definition sequencer.cc:433
#define floorf
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
void RNA_collection_clear(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
void RNA_collection_add(PointerRNA *ptr, const char *name, PointerRNA *r_value)
void RNA_struct_property_unset(PointerRNA *ptr, const char *identifier)
#define DEFAULT_IMG_STRIP_LENGTH
Definition DNA_ID.h:414
char name[258]
Definition DNA_ID.h:432
char filepath[1024]
char filepath[1024]
struct RenderData r
struct SequencerTimelineOverlay timeline_overlay
float speed_factor
float media_playback_rate
char filepath[1024]
float xmax
float xmin
float ymax
float ymin
int ymin
int xmin
eWM_DragDataType type
Definition WM_types.hh:1331
void * draw_data
Definition WM_types.hh:1402
void(* on_drag_start)(bContext *C, wmDrag *drag)
Definition WM_types.hh:1368
PointerRNA * ptr
Definition WM_types.hh:1420
void(* on_exit)(wmDropBox *drop, wmDrag *drag)
Definition WM_types.hh:1375
void(* on_enter)(wmDropBox *drop, wmDrag *drag)
Definition WM_types.hh:1371
void(* draw_in_view)(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
Definition WM_types.hh:1399
void(* draw_droptip)(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
Definition WM_types.hh:1391
int xy[2]
Definition WM_types.hh:761
struct wmEvent * eventstate
i
Definition text_draw.cc:230
wmDropBox * WM_dropbox_add(ListBase *lb, const char *idname, bool(*poll)(bContext *C, wmDrag *drag, const wmEvent *event), void(*copy)(bContext *C, wmDrag *drag, wmDropBox *drop), void(*cancel)(Main *bmain, wmDrag *drag, wmDropBox *drop), WMDropboxTooltipFunc tooltip)
blender::Span< std::string > WM_drag_get_paths(const wmDrag *drag)
int WM_drag_get_path_file_type(const wmDrag *drag)
bool WM_drag_is_ID_type(const wmDrag *drag, int idcode)
const char * WM_drag_get_single_path(const wmDrag *drag)
ID * WM_drag_get_local_ID_or_import_from_asset(const bContext *C, const wmDrag *drag, int idcode)
ListBase * WM_dropboxmap_find(const char *idname, int spaceid, int regionid)
int xy[2]
Definition wm_draw.cc:178
void WM_jobs_timer(wmJob *wm_job, double time_step, uint note, uint endnote)
Definition wm_jobs.cc:376
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition wm_jobs.cc:479
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, const void *owner, const char *name, const eWM_JobFlag flag, const eWM_JobType job_type)
Definition wm_jobs.cc:211
void WM_jobs_callbacks(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *))
Definition wm_jobs.cc:388
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *customdata))
Definition wm_jobs.cc:360
void wmOrtho2_region_pixelspace(const ARegion *region)