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
8
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) {
246 if (!g_drop_coords.has_read_mouse_pos) {
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);
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 {
564 g_drop_coords.playback_rate = 0;
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) {
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 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
#define SEQ_STRIP_OFSBOTTOM
@ SEQ_AUTO_PLAYBACK_RATE
#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.
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 producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
#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: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
#define U
ListBase * SEQ_channels_displayed_get(Editing *ed)
Definition channels.cc:23
#define floorf(x)
draw_view in_light_buf[] float
struct @157336070235062372277311340362362342103123126032::@262166344314164341202215145112231240022370055142 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)
uint color_pack(const uchar rgba[4])
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 name[66]
Definition DNA_ID.h:425
char filepath[1024]
char filepath[1024]
struct RenderData r
float media_playback_rate
struct SequencerTimelineOverlay timeline_overlay
char filepath[1024]
float xmax
float xmin
float ymax
float ymin
int ymin
int xmin
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)