Blender V4.5
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_path_utils.hh"
15#include "BLI_string.h"
16#include "BLI_string_ref.hh"
17#include "BLI_string_utils.hh"
18
19#include "BKE_context.hh"
20#include "BKE_file_handler.hh"
21#include "BKE_image.hh"
22#include "BKE_main.hh"
23
24#include "SEQ_channels.hh"
25#include "SEQ_iterator.hh"
26#include "SEQ_sequencer.hh"
27#include "SEQ_transform.hh"
28
29#include "UI_resources.hh"
30#include "UI_view2d.hh"
31
32#include "GPU_matrix.hh"
33#include "GPU_state.hh"
34
35#include "ED_screen.hh"
36#include "ED_transform.hh"
37
38#include "IMB_imbuf_types.hh"
39
40#include "MOV_read.hh"
41
42#include "WM_api.hh"
43#include "WM_types.hh"
44
45/* For querying audio files. */
46#ifdef WITH_AUDASPACE
47# include "BKE_sound.h"
48# include <AUD_Sound.h>
49# include <AUD_Special.h>
50#endif
51
52/* Own include. */
53#include "sequencer_intern.hh"
55
56namespace blender::ed::vse {
57
63 bool only_audio = false;
64 bool in_use = false;
65 bool has_read_mouse_pos = false;
69 uint8_t type;
70};
71
72/* The current drag and drop API doesn't allow us to easily pass along the
73 * required custom data to all callbacks that need it. Especially when
74 * preloading data on drag start.
75 * Therefore we will for now use a global variable for this.
76 */
78
79static void generic_poll_operations(const wmEvent *event, uint8_t type)
80{
81 g_drop_coords.type = type;
82 /* We purposely ignore the snapping tool setting here as currently other drag&drop operators only
83 * snaps when holding down Ctrl. */
84 g_drop_coords.use_snapping = event->modifier & KM_CTRL;
85}
86
87/* While drag-and-drop in the sequencer, the internal drop-box implementation allows to have a drop
88 * preview of the file dragged. This checks when drag-and-drop is done with a single file, and when
89 * only a expected `file_handler` can be used, so internal drop-box can be used instead of the
90 * `file_handler`. */
92 wmDrag *drag,
93 blender::StringRef file_handler)
94{
95 const auto paths = WM_drag_get_paths(drag);
96 auto file_handlers = blender::bke::file_handlers_poll_file_drop(C, paths);
97 return paths.size() == 1 && file_handlers.size() == 1 &&
98 file_handler == file_handlers[0]->idname;
99}
100
101static bool image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
102{
103 if (drag->type == WM_DRAG_PATH) {
105 if (file_type == FILE_TYPE_IMAGE &&
106 test_single_file_handler_poll(C, drag, "SEQUENCER_FH_image_strip"))
107 {
109 return true;
110 }
111 }
112
113 if (WM_drag_is_ID_type(drag, ID_IM)) {
115 return true;
116 }
117
118 return false;
119}
120
121static bool is_movie(wmDrag *drag)
122{
123 if (drag->type == WM_DRAG_PATH) {
125 if (file_type == FILE_TYPE_MOVIE) {
126 return true;
127 }
128 }
129 if (WM_drag_is_ID_type(drag, ID_MC)) {
130 return true;
131 }
132 return false;
133}
134
135static bool movie_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
136{
137 if (is_movie(drag) && (drag->type != WM_DRAG_PATH ||
138 test_single_file_handler_poll(C, drag, "SEQUENCER_FH_movie_strip")))
139 {
141 return true;
142 }
143
144 return false;
145}
146
147static bool is_sound(wmDrag *drag)
148{
149 if (drag->type == WM_DRAG_PATH) {
151 if (file_type == FILE_TYPE_SOUND) {
152 return true;
153 }
154 }
155 if (WM_drag_is_ID_type(drag, ID_SO)) {
156 return true;
157 }
158 return false;
159}
160
161static bool sound_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
162{
163 if (is_sound(drag) && (drag->type != WM_DRAG_PATH ||
164 test_single_file_handler_poll(C, drag, "SEQUENCER_FH_sound_strip")))
165 {
167 return true;
168 }
169
170 return false;
171}
172
173static float update_overlay_strip_position_data(bContext *C, const int mval[2])
174{
175 SeqDropCoords *coords = &g_drop_coords;
176 ARegion *region = CTX_wm_region(C);
177 Scene *scene = CTX_data_scene(C);
178 View2D *v2d = &region->v2d;
179
180 /* Update the position were we would place the strip if we complete the drag and drop action.
181 */
182 UI_view2d_region_to_view(v2d, mval[0], mval[1], &coords->start_frame, &coords->channel);
183 coords->start_frame = roundf(coords->start_frame);
184 if (coords->channel < 1.0f) {
185 coords->channel = 1;
186 }
187
188 float start_frame = coords->start_frame;
189 float end_frame;
190 float strip_len;
191
192 if (coords->playback_rate != 0.0f) {
193 float scene_playback_rate = float(scene->r.frs_sec) / scene->r.frs_sec_base;
194 strip_len = coords->strip_len / (coords->playback_rate / scene_playback_rate);
195 }
196 else if (coords->only_audio) {
197 float scene_playback_rate = float(scene->r.frs_sec) / scene->r.frs_sec_base;
198 strip_len = coords->audio_length * scene_playback_rate;
199 }
200 else {
201 strip_len = coords->strip_len;
202 }
203
204 end_frame = coords->start_frame + strip_len;
205
206 if (coords->use_snapping) {
207 /* Do snapping via the existing transform code. */
208 int snap_delta;
209 float snap_frame;
210 bool valid_snap;
211
213 scene, region, start_frame, end_frame, &snap_delta, &snap_frame);
214
215 if (valid_snap) {
216 /* We snapped onto something! */
217 start_frame += snap_delta;
218 coords->start_frame = start_frame;
219 end_frame = start_frame + strip_len;
220 coords->snap_point_x = snap_frame;
221 }
222 else {
223 /* Nothing was snapped to, disable snap drawing. */
224 coords->use_snapping = false;
225 }
226 }
227
228 /* Check if there is a strip that would intersect with the new strip(s). */
229 coords->is_intersecting = false;
230 Strip dummy_strip{};
231 seq::strip_channel_set(&dummy_strip, coords->channel);
232 dummy_strip.start = coords->start_frame;
233 dummy_strip.len = coords->strip_len;
234 dummy_strip.speed_factor = 1.0f;
235 dummy_strip.media_playback_rate = coords->playback_rate;
236 dummy_strip.flag = SEQ_AUTO_PLAYBACK_RATE;
238
239 for (int i = 0; i < coords->channel_len && !coords->is_intersecting; i++) {
240 coords->is_intersecting = seq::transform_test_overlap(scene, ed->seqbasep, &dummy_strip);
241 seq::strip_channel_set(&dummy_strip, dummy_strip.channel + 1);
242 }
243
244 return strip_len;
245}
246
247static void sequencer_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop)
248{
249 if (g_drop_coords.in_use) {
250 if (!g_drop_coords.has_read_mouse_pos) {
251 /* We didn't read the mouse position, so we need to do it manually here. */
252 int xy[2];
253 wmWindow *win = CTX_wm_window(C);
254 xy[0] = win->eventstate->xy[0];
255 xy[1] = win->eventstate->xy[1];
256
257 ARegion *region = CTX_wm_region(C);
258 int mval[2];
259 /* Convert mouse coordinates to region local coordinates. */
260 mval[0] = xy[0] - region->winrct.xmin;
261 mval[1] = xy[1] - region->winrct.ymin;
262
264 }
265
266 RNA_int_set(drop->ptr, "frame_start", g_drop_coords.start_frame);
267 RNA_int_set(drop->ptr, "channel", g_drop_coords.channel);
268 RNA_boolean_set(drop->ptr, "overlap_shuffle_override", true);
269 RNA_boolean_set(drop->ptr, "skip_locked_or_muted_channels", false);
270 }
271 else {
272 /* We are dropped inside the preview region. Put the strip on top of the
273 * current displayed frame. */
274 Scene *scene = CTX_data_scene(C);
278 SpaceSeq *sseq = CTX_wm_space_seq(C);
279
281 scene, channels, seqbase, scene->r.cfra, sseq->chanshown);
282
283 /* Get the top most strip channel that is in view. */
284 int max_channel = -1;
285 for (Strip *strip : strips) {
286 max_channel = max_ii(strip->channel, max_channel);
287 }
288
289 if (max_channel != -1) {
290 RNA_int_set(drop->ptr, "channel", max_channel);
291 }
292 }
293
295 /* ID dropped. */
296 if (id != nullptr) {
297 const ID_Type id_type = GS(id->name);
298 if (id_type == ID_IM) {
299 Image *ima = (Image *)id;
300 PointerRNA itemptr;
301 char dir[FILE_MAX], file[FILE_MAX];
302 BLI_path_split_dir_file(ima->filepath, dir, sizeof(dir), file, sizeof(file));
303 RNA_string_set(drop->ptr, "directory", dir);
304 RNA_collection_clear(drop->ptr, "files");
305 RNA_collection_add(drop->ptr, "files", &itemptr);
306 RNA_string_set(&itemptr, "name", file);
307 }
308 else if (id_type == ID_MC) {
309 MovieClip *clip = (MovieClip *)id;
310 RNA_string_set(drop->ptr, "filepath", clip->filepath);
311 RNA_struct_property_unset(drop->ptr, "name");
312 }
313 else if (id_type == ID_SO) {
314 bSound *sound = (bSound *)id;
315 RNA_string_set(drop->ptr, "filepath", sound->filepath);
316 RNA_struct_property_unset(drop->ptr, "name");
317 }
318
319 return;
320 }
321
322 const char *path = WM_drag_get_single_path(drag);
323 /* Path dropped. */
324 if (path) {
325 if (RNA_struct_find_property(drop->ptr, "filepath")) {
326 RNA_string_set(drop->ptr, "filepath", path);
327 }
328 if (RNA_struct_find_property(drop->ptr, "directory")) {
329 PointerRNA itemptr;
330 char dir[FILE_MAX], file[FILE_MAX];
331
332 BLI_path_split_dir_file(path, dir, sizeof(dir), file, sizeof(file));
333
334 RNA_string_set(drop->ptr, "directory", dir);
335
336 RNA_collection_clear(drop->ptr, "files");
337 RNA_collection_add(drop->ptr, "files", &itemptr);
338 RNA_string_set(&itemptr, "name", file);
339 }
340 }
341}
342
343static void get_drag_path(const bContext *C, wmDrag *drag, char r_path[FILE_MAX])
344{
346 /* ID dropped. */
347 if (id != nullptr) {
348 const ID_Type id_type = GS(id->name);
349 if (id_type == ID_IM) {
350 Image *ima = (Image *)id;
351 BLI_strncpy(r_path, ima->filepath, FILE_MAX);
352 }
353 else if (id_type == ID_MC) {
354 MovieClip *clip = (MovieClip *)id;
355 BLI_strncpy(r_path, clip->filepath, FILE_MAX);
356 }
357 else if (id_type == ID_SO) {
358 bSound *sound = (bSound *)id;
359 BLI_strncpy(r_path, sound->filepath, FILE_MAX);
360 }
362 }
363 else {
365 }
366}
367
368static void draw_seq_in_view(bContext *C, wmWindow * /*win*/, wmDrag *drag, const int xy[2])
369{
370 SeqDropCoords *coords = &g_drop_coords;
371 if (!coords->in_use) {
372 return;
373 }
374
375 ARegion *region = CTX_wm_region(C);
376 int mval[2];
377 /* Convert mouse coordinates to region local coordinates. */
378 mval[0] = xy[0] - region->winrct.xmin;
379 mval[1] = xy[1] - region->winrct.ymin;
380
381 float strip_len = update_overlay_strip_position_data(C, mval);
382
385
386 /* Sometimes the active theme is not the sequencer theme, e.g. when an operator invokes the
387 * file browser. This makes sure we get the right color values for the theme. */
388 bThemeState theme_state;
389 UI_Theme_Store(&theme_state);
391
392 if (coords->use_snapping) {
394 }
395
396 /* Init GPU drawing. */
398
399 /* Draw strips. The code here is taken from sequencer_draw. */
400 float x1 = coords->start_frame;
401 float x2 = coords->start_frame + floorf(strip_len);
402 uchar strip_color[4];
403 strip_color[3] = 255;
404 uchar text_color[4] = {255, 255, 255, 255};
405 float pixelx = BLI_rctf_size_x(&region->v2d.cur) / BLI_rcti_size_x(&region->v2d.mask);
406 float pixely = BLI_rctf_size_y(&region->v2d.cur) / BLI_rcti_size_y(&region->v2d.mask);
407
408 StripsDrawBatch batch(&region->v2d);
409
410 for (int i = 0; i < coords->channel_len; i++) {
411 float y1 = floorf(coords->channel) + i + STRIP_OFSBOTTOM;
412 float y2 = floorf(coords->channel) + i + STRIP_OFSTOP;
413
414 if (coords->type == TH_SEQ_MOVIE && i == 0 && coords->channel_len > 1) {
415 /* Assume only video strips occupies two channels.
416 * One for video and the other for audio.
417 * The audio channel is added first.
418 */
420 }
421 else {
422 UI_GetThemeColor3ubv(coords->type, strip_color);
423 }
424
425 SeqStripDrawData &data = batch.add_strip(x1, x2, y2, y1, y2, x1, x2, 0, true);
427 data.col_background = color_pack(strip_color);
428
429 if (coords->is_intersecting) {
430 strip_color[0] = 255;
431 strip_color[1] = strip_color[2] = 33;
432 }
433 else {
434 if (coords->channel_len - 1 == i) {
435 text_color[0] = text_color[1] = text_color[2] = 255;
437 data.flags |= GPU_SEQ_FLAG_ACTIVE;
438 }
439 else {
440 text_color[0] = text_color[1] = text_color[2] = 10;
442 }
443 }
444 strip_color[3] = 204;
445 data.col_outline = color_pack(strip_color);
446
447 const bool use_thin_handle = (U.sequencer_editor_flag & USER_SEQ_ED_SIMPLE_TWEAKING) != 0;
448 const float handle_size = use_thin_handle ? 5.0f : 8.0f;
449
450 /* Calculate height needed for drawing text on strip. */
451 float text_margin_y = y2 - min_ff(0.40f, 20 * UI_SCALE_FAC * pixely);
452 float text_margin_x = 2.0f * (pixelx * handle_size) * U.pixelsize;
453
454 rctf rect;
455 rect.xmin = x1 + text_margin_x;
456 rect.ymin = text_margin_y;
457 rect.xmax = x2 - text_margin_x;
458 rect.ymax = y2;
459
460 if (rect.xmax <= rect.xmin) {
461 /* Exit early and skip text drawing if the strip doesn't have any space to put the text
462 * into.
463 */
464 break;
465 }
466
467 SpaceSeq *sseq = CTX_wm_space_seq(C);
468 const char *text_sep = " | ";
469 const char *text_array[5];
470 char text_display[FILE_MAX];
471 char filename[FILE_MAX];
472 char path[FILE_MAX];
473 char strip_duration_text[16];
474 int len_text_arr = 0;
475
476 get_drag_path(C, drag, path);
477
479 BLI_path_split_file_part(path, filename, FILE_MAX);
480 text_array[len_text_arr++] = filename;
481 }
482
484 Main *bmain = CTX_data_main(C);
486 text_array[len_text_arr++] = text_sep;
487 text_array[len_text_arr++] = path;
488 }
489
491 SNPRINTF(strip_duration_text, "%d", int(x2 - x1));
492 text_array[len_text_arr++] = text_sep;
493 text_array[len_text_arr++] = strip_duration_text;
494 }
495
496 BLI_assert(len_text_arr <= ARRAY_SIZE(text_array));
497
498 BLI_string_join_array(text_display, FILE_MAX, text_array, len_text_arr);
499
501 &region->v2d, &rect, text_display, strlen(text_display), text_color);
502 }
503 batch.flush_batch();
504
505 /* Clean after drawing up. */
506 UI_Theme_Restore(&theme_state);
509
511}
512
514{
515 SeqDropCoords *coords = static_cast<SeqDropCoords *>(drop->draw_data);
516 if (coords && coords->in_use) {
517 return true;
518 }
519
520 coords = &g_drop_coords;
521 drop->draw_data = static_cast<void *>(&g_drop_coords);
522 coords->in_use = true;
523
524 return false;
525}
526
534};
535
536static void prefetch_data_fn(void *custom_data, wmJobWorkerStatus * /*worker_status*/)
537{
538 DropJobData *job_data = (DropJobData *)custom_data;
539
540 if (job_data->only_audio) {
541#ifdef WITH_AUDASPACE
542 /* Get the sound file length */
543 AUD_Sound *sound = AUD_Sound_file(job_data->path);
544 if (sound != nullptr) {
545
546 AUD_SoundInfo info = AUD_getInfo(sound);
547 if ((eSoundChannels)info.specs.channels != SOUND_CHANNELS_INVALID) {
548 g_drop_coords.audio_length = info.length;
549 }
550 /* The playback rate is defined by the scene. This will be computed later in
551 * #update_overlay_strip_position_data, when we know the scene from the context. So set it to
552 * 0 for now. */
553 g_drop_coords.playback_rate = 0.0f;
554 AUD_Sound_free(sound);
555 return;
556 }
557#endif
558 }
559
560 char colorspace[/*MAX_COLORSPACE_NAME*/ 64] = "\0";
561 MovieReader *anim = openanim(job_data->path, IB_byte_data, 0, colorspace);
562
563 if (anim != nullptr) {
565 g_drop_coords.playback_rate = MOV_get_fps(anim);
566 MOV_close(anim);
567#ifdef WITH_AUDASPACE
568 /* Try to load sound and see if the video has a sound channel. */
569 AUD_Sound *sound = AUD_Sound_file(job_data->path);
570 if (sound != nullptr) {
571
572 AUD_SoundInfo info = AUD_getInfo(sound);
573 if ((eSoundChannels)info.specs.channels != SOUND_CHANNELS_INVALID) {
574 g_drop_coords.channel_len = 2;
575 }
576 AUD_Sound_free(sound);
577 }
578#endif
579 }
580}
581
582static void free_prefetch_data_fn(void *custom_data)
583{
584 DropJobData *job_data = (DropJobData *)custom_data;
585 MEM_freeN(job_data);
586}
587
588static void start_audio_video_job(bContext *C, wmDrag *drag, bool only_audio)
589{
590 g_drop_coords.strip_len = 0;
591 g_drop_coords.channel_len = 1;
592
594
595 wmJob *wm_job = WM_jobs_get(wm,
596 nullptr,
597 nullptr,
598 "Loading previews...",
599 eWM_JobFlag(0),
601
602 DropJobData *job_data = MEM_mallocN<DropJobData>("SeqDragDropPreviewData");
603 get_drag_path(C, drag, job_data->path);
604
605 job_data->only_audio = only_audio;
606 g_drop_coords.only_audio = only_audio;
607
609 WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW);
610 WM_jobs_callbacks(wm_job, prefetch_data_fn, nullptr, nullptr, nullptr);
611
612 WM_jobs_start(wm, wm_job);
613}
614
615static void video_prefetch(bContext *C, wmDrag *drag)
616{
617 if (is_movie(drag)) {
618 start_audio_video_job(C, drag, false);
619 }
620}
621
622static void audio_prefetch(bContext *C, wmDrag *drag)
623{
624 if (is_sound(drag)) {
625 start_audio_video_job(C, drag, true);
626 }
627}
628
629static void movie_drop_on_enter(wmDropBox *drop, wmDrag * /*drag*/)
630{
631 if (generic_drop_draw_handling(drop)) {
632 return;
633 }
634}
635
636static void sound_drop_on_enter(wmDropBox *drop, wmDrag * /*drag*/)
637{
638 if (generic_drop_draw_handling(drop)) {
639 return;
640 }
641}
642
643static void image_drop_on_enter(wmDropBox *drop, wmDrag * /*drag*/)
644{
645 if (generic_drop_draw_handling(drop)) {
646 return;
647 }
648
649 SeqDropCoords *coords = static_cast<SeqDropCoords *>(drop->draw_data);
651 coords->channel_len = 1;
652}
653
654static void sequencer_drop_on_exit(wmDropBox *drop, wmDrag * /*drag*/)
655{
656 SeqDropCoords *coords = static_cast<SeqDropCoords *>(drop->draw_data);
657 if (coords) {
658 coords->in_use = false;
659 coords->has_read_mouse_pos = false;
660 drop->draw_data = nullptr;
661 }
662}
663
664static void nop_draw_droptip_fn(bContext * /*C*/,
665 wmWindow * /*win*/,
666 wmDrag * /*drag*/,
667 const int /*xy*/[2])
668{
669 /* Do nothing in here.
670 * This is to prevent the default drag and drop mouse overlay to be drawn.
671 */
672}
673
674/* This region dropbox definition. */
676{
677 wmDropBox *drop;
678 drop = WM_dropbox_add(
679 lb, "SEQUENCER_OT_image_strip_add", image_drop_poll, sequencer_drop_copy, nullptr, nullptr);
684
686
687 drop = WM_dropbox_add(
688 lb, "SEQUENCER_OT_movie_strip_add", movie_drop_poll, sequencer_drop_copy, nullptr, nullptr);
693
695
696 drop = WM_dropbox_add(
697 lb, "SEQUENCER_OT_sound_strip_add", sound_drop_poll, sequencer_drop_copy, nullptr, nullptr);
702}
703
704static bool image_drop_preview_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*event*/)
705{
706 if (drag->type == WM_DRAG_PATH) {
708 if (file_type == FILE_TYPE_IMAGE) {
709 return true;
710 }
711 }
712
713 return WM_drag_is_ID_type(drag, ID_IM);
714}
715
716static bool movie_drop_preview_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*event*/)
717{
718 if (drag->type == WM_DRAG_PATH) {
720 if (file_type == FILE_TYPE_MOVIE) {
721 return true;
722 }
723 }
724
725 return WM_drag_is_ID_type(drag, ID_MC);
726}
727
728static bool sound_drop_preview_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*event*/)
729{
730 if (drag->type == WM_DRAG_PATH) {
732 if (file_type == FILE_TYPE_SOUND) {
733 return true;
734 }
735 }
736
737 return WM_drag_is_ID_type(drag, ID_SO);
738}
739
741{
743 "SEQUENCER_OT_image_strip_add",
746 nullptr,
747 nullptr);
748
750 "SEQUENCER_OT_movie_strip_add",
753 nullptr,
754 nullptr);
755
757 "SEQUENCER_OT_sound_strip_add",
760 nullptr,
761 nullptr);
762}
763
771
772} // namespace blender::ed::vse
wmWindow * CTX_wm_window(const bContext *C)
Scene * CTX_data_scene(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)
MovieReader * openanim(const char *filepath, int flags, int streamindex, char colorspace[IMA_MAX_SPACE])
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:872
const char * BKE_main_blendfile_path_from_global()
Definition main.cc:877
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
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:599
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
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)
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
@ USER_SEQ_ED_SIMPLE_TWEAKING
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(eGPUBlend 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:2141
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:2111
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:1667
@ WM_JOB_TYPE_SEQ_DRAG_DROP_PREVIEW
Definition WM_api.hh:1758
eWM_JobFlag
Definition WM_api.hh:1709
#define NC_WINDOW
Definition WM_types.hh:372
@ KM_CTRL
Definition WM_types.hh:276
@ WM_DRAG_PATH
Definition WM_types.hh:1205
#define U
BMesh const char void * data
#define floorf(x)
struct @064345207361167251075330302113175271221317160336::@113254110077376341056327177062323111323010325277 batch
#define GS(a)
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:58
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 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 draw_seq_in_view(bContext *C, wmWindow *, wmDrag *drag, const int xy[2])
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:277
VectorSet< Strip * > query_rendered_strips(const Scene *scene, ListBase *channels, ListBase *seqbase, const int timeline_frame, const int displayed_channel)
Definition iterator.cc:205
ListBase * active_seqbase_get(const Editing *ed)
Definition sequencer.cc:420
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:404
char name[66]
Definition DNA_ID.h:415
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:1327
void * draw_data
Definition WM_types.hh:1397
void(* on_drag_start)(bContext *C, wmDrag *drag)
Definition WM_types.hh:1363
PointerRNA * ptr
Definition WM_types.hh:1415
void(* on_exit)(wmDropBox *drop, wmDrag *drag)
Definition WM_types.hh:1370
void(* on_enter)(wmDropBox *drop, wmDrag *drag)
Definition WM_types.hh:1366
void(* draw_in_view)(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
Definition WM_types.hh:1394
void(* draw_droptip)(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
Definition WM_types.hh:1386
int xy[2]
Definition WM_types.hh:758
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:174
void WM_jobs_timer(wmJob *wm_job, double time_step, uint note, uint endnote)
Definition wm_jobs.cc:353
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition wm_jobs.cc:456
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:190
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:365
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *customdata))
Definition wm_jobs.cc:337
void wmOrtho2_region_pixelspace(const ARegion *region)