Blender V4.3
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
9#include "MEM_guardedalloc.h"
10
11#include "DNA_scene_types.h"
12#include "DNA_sound_types.h"
13
14#include "BLI_blenlib.h"
15#include "BLI_string_ref.hh"
16#include "BLI_string_utils.hh"
17
18#include "BKE_context.hh"
19#include "BKE_file_handler.hh"
20#include "BKE_image.hh"
21#include "BKE_main.hh"
22
23#include "SEQ_channels.hh"
24#include "SEQ_iterator.hh"
25#include "SEQ_sequencer.hh"
26#include "SEQ_transform.hh"
27
28#include "UI_resources.hh"
29#include "UI_view2d.hh"
30
31#include "GPU_matrix.hh"
32
33#include "ED_screen.hh"
34#include "ED_transform.hh"
35
36#include "IMB_imbuf.hh"
37#include "IMB_imbuf_types.hh"
38
39#include "WM_api.hh"
40#include "WM_types.hh"
41
42/* For querying audio files. */
43#ifdef WITH_AUDASPACE
44# include "BKE_sound.h"
45# include <AUD_Sound.h>
46# include <AUD_Special.h>
47#endif
48
49/* Own include. */
50#include "sequencer_intern.hh"
52
64
65/* The current drag and drop API doesn't allow us to easily pass along the
66 * required custom data to all callbacks that need it. Especially when
67 * preloading data on drag start.
68 * Therefore we will for now use a global variable for this.
69 */
71
72static void generic_poll_operations(const wmEvent *event, uint8_t type)
73{
74 g_drop_coords.type = type;
75 /* We purposely ignore the snapping tool setting here as currently other drag&drop operators only
76 * snaps when holding down Ctrl. */
77 g_drop_coords.use_snapping = event->modifier & KM_CTRL;
78}
79
80/* While drag-and-drop in the sequencer, the internal drop-box implementation allows to have a drop
81 * preview of the file dragged. This checks when drag-and-drop is done with a single file, and when
82 * only a expected `file_handler` can be used, so internal drop-box can be used instead of the
83 * `file_handler`. */
85 wmDrag *drag,
86 blender::StringRef file_handler)
87{
88 const auto paths = WM_drag_get_paths(drag);
89 auto file_handlers = blender::bke::file_handlers_poll_file_drop(C, paths);
90 return paths.size() == 1 && file_handlers.size() == 1 &&
91 file_handler == file_handlers[0]->idname;
92}
93
94static bool image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
95{
96 if (drag->type == WM_DRAG_PATH) {
98 if (file_type == FILE_TYPE_IMAGE &&
99 test_single_file_handler_poll(C, drag, "SEQUENCER_FH_image_strip"))
100 {
102 return true;
103 }
104 }
105
106 if (WM_drag_is_ID_type(drag, ID_IM)) {
108 return true;
109 }
110
111 return false;
112}
113
114static bool is_movie(wmDrag *drag)
115{
116 if (drag->type == WM_DRAG_PATH) {
118 if (file_type == FILE_TYPE_MOVIE) {
119 return true;
120 }
121 }
122 if (WM_drag_is_ID_type(drag, ID_MC)) {
123 return true;
124 }
125 return false;
126}
127
128static bool movie_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
129{
130 if (is_movie(drag) && (drag->type != WM_DRAG_PATH ||
131 test_single_file_handler_poll(C, drag, "SEQUENCER_FH_movie_strip")))
132 {
134 return true;
135 }
136
137 return false;
138}
139
140static bool is_sound(wmDrag *drag)
141{
142 if (drag->type == WM_DRAG_PATH) {
144 if (file_type == FILE_TYPE_SOUND) {
145 return true;
146 }
147 }
148 if (WM_drag_is_ID_type(drag, ID_SO)) {
149 return true;
150 }
151 return false;
152}
153
154static bool sound_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
155{
156 if (is_sound(drag) && (drag->type != WM_DRAG_PATH ||
157 test_single_file_handler_poll(C, drag, "SEQUENCER_FH_sound_strip")))
158 {
160 return true;
161 }
162
163 return false;
164}
165
166static float update_overlay_strip_position_data(bContext *C, const int mval[2])
167{
168 SeqDropCoords *coords = &g_drop_coords;
169 ARegion *region = CTX_wm_region(C);
170 Scene *scene = CTX_data_scene(C);
171 eSeqHandle hand;
172 View2D *v2d = &region->v2d;
173
174 /* Update the position were we would place the strip if we complete the drag and drop action.
175 */
176 UI_view2d_region_to_view(v2d, mval[0], mval[1], &coords->start_frame, &coords->channel);
177 coords->start_frame = roundf(coords->start_frame);
178 if (coords->channel < 1.0f) {
179 coords->channel = 1;
180 }
181
182 float start_frame = coords->start_frame;
183 float end_frame;
184 float strip_len;
185
186 if (coords->playback_rate != 0.0f) {
187 float scene_playback_rate = float(scene->r.frs_sec) / scene->r.frs_sec_base;
188 strip_len = coords->strip_len / (coords->playback_rate / scene_playback_rate);
189 }
190 else {
191 strip_len = coords->strip_len;
192 }
193
194 end_frame = coords->start_frame + strip_len;
195
196 if (coords->use_snapping) {
197 /* Do snapping via the existing transform code. */
198 int snap_delta;
199 float snap_frame;
200 bool valid_snap;
201
203 scene, region, start_frame, end_frame, &snap_delta, &snap_frame);
204
205 if (valid_snap) {
206 /* We snapped onto something! */
207 start_frame += snap_delta;
208 coords->start_frame = start_frame;
209 end_frame = start_frame + strip_len;
210 coords->snap_point_x = snap_frame;
211 }
212 else {
213 /* Nothing was snapped to, disable snap drawing. */
214 coords->use_snapping = false;
215 }
216 }
217
218 if (strip_len < 1) {
219 /* Only check if there is a strip already under the mouse cursor. */
220 coords->is_intersecting = find_nearest_seq(scene, &region->v2d, mval, &hand);
221 }
222 else {
223 /* Check if there is a strip that would intersect with the new strip(s). */
224 coords->is_intersecting = false;
225 Sequence dummy_seq{};
226 dummy_seq.machine = coords->channel;
227 dummy_seq.start = coords->start_frame;
228 dummy_seq.len = coords->strip_len;
229 dummy_seq.speed_factor = 1.0f;
230 dummy_seq.media_playback_rate = coords->playback_rate;
231 dummy_seq.flag = SEQ_AUTO_PLAYBACK_RATE;
232 Editing *ed = SEQ_editing_ensure(scene);
233
234 for (int i = 0; i < coords->channel_len && !coords->is_intersecting; i++) {
235 coords->is_intersecting = SEQ_transform_test_overlap(scene, ed->seqbasep, &dummy_seq);
236 dummy_seq.machine++;
237 }
238 }
239
240 return strip_len;
241}
242
243static void sequencer_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop)
244{
245 if (g_drop_coords.in_use) {
247 /* We didn't read the mouse position, so we need to do it manually here. */
248 int xy[2];
249 wmWindow *win = CTX_wm_window(C);
250 xy[0] = win->eventstate->xy[0];
251 xy[1] = win->eventstate->xy[1];
252
253 ARegion *region = CTX_wm_region(C);
254 int mval[2];
255 /* Convert mouse coordinates to region local coordinates. */
256 mval[0] = xy[0] - region->winrct.xmin;
257 mval[1] = xy[1] - region->winrct.ymin;
258
260 }
261
262 RNA_int_set(drop->ptr, "frame_start", g_drop_coords.start_frame);
263 RNA_int_set(drop->ptr, "channel", g_drop_coords.channel);
264 RNA_boolean_set(drop->ptr, "overlap_shuffle_override", true);
265 }
266 else {
267 /* We are dropped inside the preview region. Put the strip on top of the
268 * current displayed frame. */
269 Scene *scene = CTX_data_scene(C);
270 Editing *ed = SEQ_editing_ensure(scene);
271 ListBase *seqbase = SEQ_active_seqbase_get(ed);
272 ListBase *channels = SEQ_channels_displayed_get(ed);
273 SpaceSeq *sseq = CTX_wm_space_seq(C);
274
276 scene, channels, seqbase, scene->r.cfra, sseq->chanshown);
277
278 /* Get the top most strip channel that is in view. */
279 int max_channel = -1;
280 for (Sequence *seq : strips) {
281 max_channel = max_ii(seq->machine, max_channel);
282 }
283
284 if (max_channel != -1) {
285 RNA_int_set(drop->ptr, "channel", max_channel);
286 }
287 }
288
290 /* ID dropped. */
291 if (id != nullptr) {
292 const ID_Type id_type = GS(id->name);
293 if (id_type == ID_IM) {
294 Image *ima = (Image *)id;
295 PointerRNA itemptr;
296 char dir[FILE_MAX], file[FILE_MAX];
297 BLI_path_split_dir_file(ima->filepath, dir, sizeof(dir), file, sizeof(file));
298 RNA_string_set(drop->ptr, "directory", dir);
299 RNA_collection_clear(drop->ptr, "files");
300 RNA_collection_add(drop->ptr, "files", &itemptr);
301 RNA_string_set(&itemptr, "name", file);
302 }
303 else if (id_type == ID_MC) {
304 MovieClip *clip = (MovieClip *)id;
305 RNA_string_set(drop->ptr, "filepath", clip->filepath);
306 RNA_struct_property_unset(drop->ptr, "name");
307 }
308 else if (id_type == ID_SO) {
309 bSound *sound = (bSound *)id;
310 RNA_string_set(drop->ptr, "filepath", sound->filepath);
311 RNA_struct_property_unset(drop->ptr, "name");
312 }
313
314 return;
315 }
316
317 const char *path = WM_drag_get_single_path(drag);
318 /* Path dropped. */
319 if (path) {
320 if (RNA_struct_find_property(drop->ptr, "filepath")) {
321 RNA_string_set(drop->ptr, "filepath", path);
322 }
323 if (RNA_struct_find_property(drop->ptr, "directory")) {
324 PointerRNA itemptr;
325 char dir[FILE_MAX], file[FILE_MAX];
326
327 BLI_path_split_dir_file(path, dir, sizeof(dir), file, sizeof(file));
328
329 RNA_string_set(drop->ptr, "directory", dir);
330
331 RNA_collection_clear(drop->ptr, "files");
332 RNA_collection_add(drop->ptr, "files", &itemptr);
333 RNA_string_set(&itemptr, "name", file);
334 }
335 }
336}
337
338static void get_drag_path(const bContext *C, wmDrag *drag, char r_path[FILE_MAX])
339{
341 /* ID dropped. */
342 if (id != nullptr) {
343 const ID_Type id_type = GS(id->name);
344 if (id_type == ID_IM) {
345 Image *ima = (Image *)id;
346 BLI_strncpy(r_path, ima->filepath, FILE_MAX);
347 }
348 else if (id_type == ID_MC) {
349 MovieClip *clip = (MovieClip *)id;
350 BLI_strncpy(r_path, clip->filepath, FILE_MAX);
351 }
352 else if (id_type == ID_SO) {
353 bSound *sound = (bSound *)id;
354 BLI_strncpy(r_path, sound->filepath, FILE_MAX);
355 }
357 }
358 else {
360 }
361}
362
363static void draw_seq_in_view(bContext *C, wmWindow * /*win*/, wmDrag *drag, const int xy[2])
364{
365 using namespace blender::ed::seq;
366 SeqDropCoords *coords = &g_drop_coords;
367 if (!coords->in_use) {
368 return;
369 }
370
371 ARegion *region = CTX_wm_region(C);
372 int mval[2];
373 /* Convert mouse coordinates to region local coordinates. */
374 mval[0] = xy[0] - region->winrct.xmin;
375 mval[1] = xy[1] - region->winrct.ymin;
376
377 float strip_len = update_overlay_strip_position_data(C, mval);
378
381
382 /* Sometimes the active theme is not the sequencer theme, e.g. when an operator invokes the
383 * file browser. This makes sure we get the right color values for the theme. */
384 bThemeState theme_state;
385 UI_Theme_Store(&theme_state);
387
388 if (coords->use_snapping) {
390 }
391
392 /* Init GPU drawing. */
394
395 /* Draw strips. The code here is taken from sequencer_draw. */
396 float x1 = coords->start_frame;
397 float x2 = coords->start_frame + floorf(strip_len);
398 uchar strip_color[4];
399 strip_color[3] = 255;
400 uchar text_color[4] = {255, 255, 255, 255};
401 float pixelx = BLI_rctf_size_x(&region->v2d.cur) / BLI_rcti_size_x(&region->v2d.mask);
402 float pixely = BLI_rctf_size_y(&region->v2d.cur) / BLI_rcti_size_y(&region->v2d.mask);
403
404 StripsDrawBatch batch(&region->v2d);
405
406 for (int i = 0; i < coords->channel_len; i++) {
407 float y1 = floorf(coords->channel) + i + SEQ_STRIP_OFSBOTTOM;
408 float y2 = floorf(coords->channel) + i + SEQ_STRIP_OFSTOP;
409
410 if (coords->type == TH_SEQ_MOVIE && i == 0 && coords->channel_len > 1) {
411 /* Assume only video strips occupies two channels.
412 * One for video and the other for audio.
413 * The audio channel is added first.
414 */
416 }
417 else {
418 UI_GetThemeColor3ubv(coords->type, strip_color);
419 }
420
421 SeqStripDrawData &data = batch.add_strip(x1, x2, y2, y1, y2, x1, x2, 0, true);
423 data.col_background = color_pack(strip_color);
424
425 if (coords->is_intersecting) {
426 strip_color[0] = 255;
427 strip_color[1] = strip_color[2] = 33;
428 }
429 else {
430 if (coords->channel_len - 1 == i) {
431 text_color[0] = text_color[1] = text_color[2] = 255;
433 data.flags |= GPU_SEQ_FLAG_ACTIVE;
434 }
435 else {
436 text_color[0] = text_color[1] = text_color[2] = 10;
438 }
439 }
440 strip_color[3] = 204;
441 data.col_outline = color_pack(strip_color);
442
443 const bool use_thin_handle = (U.sequencer_editor_flag & USER_SEQ_ED_SIMPLE_TWEAKING) != 0;
444 const float handle_size = use_thin_handle ? 5.0f : 8.0f;
445
446 /* Calculate height needed for drawing text on strip. */
447 float text_margin_y = y2 - min_ff(0.40f, 20 * UI_SCALE_FAC * pixely);
448 float text_margin_x = 2.0f * (pixelx * handle_size) * U.pixelsize;
449
450 rctf rect;
451 rect.xmin = x1 + text_margin_x;
452 rect.ymin = text_margin_y;
453 rect.xmax = x2 - text_margin_x;
454 rect.ymax = y2;
455
456 if (rect.xmax <= rect.xmin) {
457 /* Exit early and skip text drawing if the strip doesn't have any space to put the text
458 * into.
459 */
460 break;
461 }
462
463 SpaceSeq *sseq = CTX_wm_space_seq(C);
464 const char *text_sep = " | ";
465 const char *text_array[5];
466 char text_display[FILE_MAX];
467 char filename[FILE_MAX];
468 char path[FILE_MAX];
469 char strip_duration_text[16];
470 int len_text_arr = 0;
471
472 get_drag_path(C, drag, path);
473
475 BLI_path_split_file_part(path, filename, FILE_MAX);
476 text_array[len_text_arr++] = filename;
477 }
478
480 Main *bmain = CTX_data_main(C);
482 text_array[len_text_arr++] = text_sep;
483 text_array[len_text_arr++] = path;
484 }
485
487 SNPRINTF(strip_duration_text, "%d", int(x2 - x1));
488 text_array[len_text_arr++] = text_sep;
489 text_array[len_text_arr++] = strip_duration_text;
490 }
491
492 BLI_assert(len_text_arr <= ARRAY_SIZE(text_array));
493
494 BLI_string_join_array(text_display, FILE_MAX, text_array, len_text_arr);
495
497 &region->v2d, &rect, text_display, strlen(text_display), text_color);
498 }
499 batch.flush_batch();
500
501 /* Clean after drawing up. */
502 UI_Theme_Restore(&theme_state);
505
507}
508
510{
511 SeqDropCoords *coords = static_cast<SeqDropCoords *>(drop->draw_data);
512 if (coords && coords->in_use) {
513 return true;
514 }
515
516 coords = &g_drop_coords;
517 drop->draw_data = static_cast<void *>(&g_drop_coords);
518 coords->in_use = true;
519
520 return false;
521}
522
531};
532
533static void prefetch_data_fn(void *custom_data, wmJobWorkerStatus * /*worker_status*/)
534{
535 DropJobData *job_data = (DropJobData *)custom_data;
536
537 if (job_data->only_audio) {
538#ifdef WITH_AUDASPACE
539 /* Get the sound file length */
540 AUD_Sound *sound = AUD_Sound_file(job_data->path);
541 if (sound != nullptr) {
542
543 AUD_SoundInfo info = AUD_getInfo(sound);
544 if ((eSoundChannels)info.specs.channels != SOUND_CHANNELS_INVALID) {
545 g_drop_coords.strip_len = max_ii(1, round((info.length) * job_data->scene_fps));
546 }
547 AUD_Sound_free(sound);
548 return;
549 }
550#endif
551 }
552
553 char colorspace[64] = "\0"; /* 64 == MAX_COLORSPACE_NAME length. */
554 ImBufAnim *anim = openanim(job_data->path, IB_rect, 0, colorspace);
555
556 if (anim != nullptr) {
558 short frs_sec;
559 float frs_sec_base;
560 if (IMB_anim_get_fps(anim, true, &frs_sec, &frs_sec_base)) {
561 g_drop_coords.playback_rate = float(frs_sec) / frs_sec_base;
562 }
563 else {
565 }
566 IMB_free_anim(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) {
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{
592
594 wmWindow *win = CTX_wm_window(C);
595 Scene *scene = CTX_data_scene(C);
596
597 wmJob *wm_job = WM_jobs_get(
598 wm, win, nullptr, "Load Previews", eWM_JobFlag(0), WM_JOB_TYPE_SEQ_DRAG_DROP_PREVIEW);
599
600 DropJobData *job_data = (DropJobData *)MEM_mallocN(sizeof(DropJobData),
601 "SeqDragDropPreviewData");
602 get_drag_path(C, drag, job_data->path);
603
604 job_data->only_audio = only_audio;
605 job_data->scene_fps = FPS;
606
608 WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW);
609 WM_jobs_callbacks(wm_job, prefetch_data_fn, nullptr, nullptr, nullptr);
610
611 WM_jobs_start(wm, wm_job);
612}
613
614static void video_prefetch(bContext *C, wmDrag *drag)
615{
616 if (is_movie(drag)) {
617 start_audio_video_job(C, drag, false);
618 }
619}
620
621static void audio_prefetch(bContext *C, wmDrag *drag)
622{
623 if (is_sound(drag)) {
624 start_audio_video_job(C, drag, true);
625 }
626}
627
628static void movie_drop_on_enter(wmDropBox *drop, wmDrag * /*drag*/)
629{
630 if (generic_drop_draw_handling(drop)) {
631 return;
632 }
633}
634
635static void sound_drop_on_enter(wmDropBox *drop, wmDrag * /*drag*/)
636{
637 if (generic_drop_draw_handling(drop)) {
638 return;
639 }
640}
641
642static void image_drop_on_enter(wmDropBox *drop, wmDrag * /*drag*/)
643{
644 if (generic_drop_draw_handling(drop)) {
645 return;
646 }
647
648 SeqDropCoords *coords = static_cast<SeqDropCoords *>(drop->draw_data);
650 coords->channel_len = 1;
651}
652
653static void sequencer_drop_on_exit(wmDropBox *drop, wmDrag * /*drag*/)
654{
655 SeqDropCoords *coords = static_cast<SeqDropCoords *>(drop->draw_data);
656 if (coords) {
657 coords->in_use = false;
658 coords->has_read_mouse_pos = false;
659 drop->draw_data = nullptr;
660 }
661}
662
663static void nop_draw_droptip_fn(bContext * /*C*/,
664 wmWindow * /*win*/,
665 wmDrag * /*drag*/,
666 const int /*xy*/[2])
667{
668 /* Do nothing in here.
669 * This is to prevent the default drag and drop mouse overlay to be drawn.
670 */
671}
672
673/* This region dropbox definition. */
675{
676 wmDropBox *drop;
677 drop = WM_dropbox_add(
678 lb, "SEQUENCER_OT_image_strip_add", image_drop_poll, sequencer_drop_copy, nullptr, nullptr);
683
685
686 drop = WM_dropbox_add(
687 lb, "SEQUENCER_OT_movie_strip_add", movie_drop_poll, sequencer_drop_copy, nullptr, nullptr);
692
694
695 drop = WM_dropbox_add(
696 lb, "SEQUENCER_OT_sound_strip_add", sound_drop_poll, sequencer_drop_copy, nullptr, nullptr);
701}
702
703static bool image_drop_preview_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*event*/)
704{
705 if (drag->type == WM_DRAG_PATH) {
707 if (file_type == FILE_TYPE_IMAGE) {
708 return true;
709 }
710 }
711
712 return WM_drag_is_ID_type(drag, ID_IM);
713}
714
715static bool movie_drop_preview_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*event*/)
716{
717 if (drag->type == WM_DRAG_PATH) {
719 if (file_type == FILE_TYPE_MOVIE) {
720 return true;
721 }
722 }
723
724 return WM_drag_is_ID_type(drag, ID_MC);
725}
726
727static bool sound_drop_preview_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*event*/)
728{
729 if (drag->type == WM_DRAG_PATH) {
731 if (file_type == FILE_TYPE_SOUND) {
732 return true;
733 }
734 }
735
736 return WM_drag_is_ID_type(drag, ID_SO);
737}
738
740{
742 "SEQUENCER_OT_image_strip_add",
745 nullptr,
746 nullptr);
747
749 "SEQUENCER_OT_movie_strip_add",
752 nullptr,
753 nullptr);
754
756 "SEQUENCER_OT_sound_strip_add",
759 nullptr,
760 nullptr);
761}
762
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)
ImBufAnim * 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:832
const char * BKE_main_blendfile_path_from_global()
Definition main.cc:837
eSoundChannels
Definition BKE_sound.h:68
@ SOUND_CHANNELS_INVALID
Definition BKE_sound.h:69
#define BLI_assert(a)
Definition BLI_assert.h:50
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:193
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:189
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition BLI_rect.h:197
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition BLI_rect.h:201
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
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
#define FPS
@ RGN_TYPE_WINDOW
@ RGN_TYPE_PREVIEW
@ SEQ_AUTO_PLAYBACK_RATE
#define SEQ_STRIP_OFSBOTTOM
#define SEQ_STRIP_OFSTOP
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
eSeqHandle
bool ED_transform_snap_sequencer_to_closest_strip_calc(Scene *scene, ARegion *region, int frame_1, int frame_2, int *r_snap_distance, float *r_snap_frame)
void ED_draw_sequencer_snap_point(ARegion *region, float snap_point)
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
bool IMB_anim_get_fps(const ImBufAnim *anim, bool no_av_base, short *r_frs_sec, float *r_frs_sec_base)
void IMB_free_anim(ImBufAnim *anim)
Definition anim_movie.cc:60
int IMB_anim_get_duration(ImBufAnim *anim, IMB_Timecode_Type tc)
@ IMB_TC_NONE
Contains defines and structs used throughout the imbuf module.
@ IB_rect
Read Guarded memory(de)allocation.
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:2137
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:2107
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:1663
@ WM_JOB_TYPE_SEQ_DRAG_DROP_PREVIEW
Definition WM_api.hh:1608
eWM_JobFlag
Definition WM_api.hh:1559
#define NC_WINDOW
Definition WM_types.hh:342
@ WM_DRAG_PATH
Definition WM_types.hh:1160
@ KM_CTRL
Definition WM_types.hh:256
unsigned int U
Definition btGjkEpa3.h:78
ListBase * SEQ_channels_displayed_get(Editing *ed)
Definition channels.cc:23
#define floorf(x)
draw_view in_light_buf[] float
struct @620::@622 batch
#define GS(x)
Definition iris.cc:202
VectorSet< Sequence * > SEQ_query_rendered_strips(const Scene *scene, ListBase *channels, ListBase *seqbase, const int timeline_frame, const int displayed_channel)
Definition iterator.cc:184
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
blender::Vector< FileHandlerType * > file_handlers_poll_file_drop(const bContext *C, const blender::Span< std::string > paths)
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)
Editing * SEQ_editing_ensure(Scene *scene)
Definition sequencer.cc:267
ListBase * SEQ_active_seqbase_get(const Editing *ed)
Definition sequencer.cc:416
static float update_overlay_strip_position_data(bContext *C, const int mval[2])
void sequencer_dropboxes()
static bool test_single_file_handler_poll(const bContext *C, wmDrag *drag, blender::StringRef file_handler)
static bool image_drop_preview_poll(bContext *, wmDrag *drag, const wmEvent *)
static void get_drag_path(const bContext *C, wmDrag *drag, char r_path[FILE_MAX])
static void start_audio_video_job(bContext *C, wmDrag *drag, bool only_audio)
static void generic_poll_operations(const wmEvent *event, uint8_t type)
static void audio_prefetch(bContext *C, wmDrag *drag)
static void video_prefetch(bContext *C, wmDrag *drag)
static bool movie_drop_preview_poll(bContext *, wmDrag *drag, const wmEvent *)
static void sequencer_dropboxes_add_to_lb(ListBase *lb)
static void sound_drop_on_enter(wmDropBox *drop, wmDrag *)
static bool movie_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
static void prefetch_data_fn(void *custom_data, wmJobWorkerStatus *)
static void image_drop_on_enter(wmDropBox *drop, wmDrag *)
static void draw_seq_in_view(bContext *C, wmWindow *, wmDrag *drag, const int xy[2])
static void nop_draw_droptip_fn(bContext *, wmWindow *, wmDrag *, const int[2])
static void sequencer_preview_dropboxes_add_to_lb(ListBase *lb)
static void sequencer_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop)
static void free_prefetch_data_fn(void *custom_data)
static bool generic_drop_draw_handling(wmDropBox *drop)
static bool sound_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
static bool is_movie(wmDrag *drag)
static bool is_sound(wmDrag *drag)
static bool image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
static void sequencer_drop_on_exit(wmDropBox *drop, wmDrag *)
static bool sound_drop_preview_poll(bContext *, wmDrag *drag, const wmEvent *)
static SeqDropCoords g_drop_coords
static void movie_drop_on_enter(wmDropBox *drop, wmDrag *)
Sequence * find_nearest_seq(const Scene *scene, const View2D *v2d, const int mval[2], eSeqHandle *r_hand)
#define DEFAULT_IMG_STRIP_LENGTH
unsigned char uint8_t
Definition stdint.h:78
bool SEQ_transform_test_overlap(const Scene *scene, ListBase *seqbasep, Sequence *test)
char path[FILE_MAX]
ListBase * seqbasep
Definition DNA_ID.h:413
char filepath[1024]
struct SequencerTimelineOverlay timeline_overlay
char filepath[1024]
float xmax
float xmin
float ymax
float ymin
eWM_DragDataType type
Definition WM_types.hh:1282
void * draw_data
Definition WM_types.hh:1350
void(* on_drag_start)(bContext *C, wmDrag *drag)
Definition WM_types.hh:1316
PointerRNA * ptr
Definition WM_types.hh:1368
void(* on_exit)(wmDropBox *drop, wmDrag *drag)
Definition WM_types.hh:1323
void(* on_enter)(wmDropBox *drop, wmDrag *drag)
Definition WM_types.hh:1319
void(* draw_in_view)(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
Definition WM_types.hh:1347
void(* draw_droptip)(bContext *C, wmWindow *win, wmDrag *drag, const int xy[2])
Definition WM_types.hh:1339
int xy[2]
Definition WM_types.hh:726
struct wmEvent * eventstate
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:170
void WM_jobs_timer(wmJob *wm_job, double time_step, uint note, uint endnote)
Definition wm_jobs.cc:352
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition wm_jobs.cc:455
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:189
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:364
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *customdata))
Definition wm_jobs.cc:336
void wmOrtho2_region_pixelspace(const ARegion *region)