Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/space_sequencer/sequencer_drag_drop.c
| /* SPDX-License-Identifier: GPL-2.0-or-later | /* SPDX-License-Identifier: GPL-2.0-or-later | ||||
| * Copyright 2022 Blender Foundation. All rights reserved. */ | * Copyright 2022 Blender Foundation. All rights reserved. */ | ||||
| /** \file | /** \file | ||||
| * \ingroup spseq | * \ingroup spseq | ||||
| */ | */ | ||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #include "DNA_scene_types.h" | #include "DNA_scene_types.h" | ||||
| #include "DNA_sound_types.h" | #include "DNA_sound_types.h" | ||||
| #include "DNA_video_edit_types.h" | |||||
| #include "BLI_blenlib.h" | #include "BLI_blenlib.h" | ||||
| #include "BLI_string_utils.h" | #include "BLI_string_utils.h" | ||||
| #include "BKE_context.h" | #include "BKE_context.h" | ||||
| #include "BKE_global.h" | #include "BKE_global.h" | ||||
| #include "BKE_image.h" | #include "BKE_image.h" | ||||
| #include "BKE_main.h" | #include "BKE_main.h" | ||||
| ▲ Show 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | static bool sound_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *event) | ||||
| return false; | return false; | ||||
| } | } | ||||
| static float update_overlay_strip_position_data(bContext *C, const int mval[2]) | static float update_overlay_strip_position_data(bContext *C, const int mval[2]) | ||||
| { | { | ||||
| SeqDropCoords *coords = &g_drop_coords; | SeqDropCoords *coords = &g_drop_coords; | ||||
| ARegion *region = CTX_wm_region(C); | ARegion *region = CTX_wm_region(C); | ||||
| Scene *scene = CTX_data_scene(C); | VideoEdit *video_edit = CTX_data_video_edit(C); | ||||
| int hand; | int hand; | ||||
| View2D *v2d = ®ion->v2d; | View2D *v2d = ®ion->v2d; | ||||
| /* Update the position were we would place the strip if we complete the drag and drop action. | /* Update the position were we would place the strip if we complete the drag and drop action. | ||||
| */ | */ | ||||
| UI_view2d_region_to_view(v2d, mval[0], mval[1], &coords->start_frame, &coords->channel); | UI_view2d_region_to_view(v2d, mval[0], mval[1], &coords->start_frame, &coords->channel); | ||||
| coords->start_frame = roundf(coords->start_frame); | coords->start_frame = roundf(coords->start_frame); | ||||
| if (coords->channel < 1.0f) { | if (coords->channel < 1.0f) { | ||||
| coords->channel = 1; | coords->channel = 1; | ||||
| } | } | ||||
| float start_frame = coords->start_frame; | float start_frame = coords->start_frame; | ||||
| float end_frame; | float end_frame; | ||||
| float strip_len; | float strip_len; | ||||
| if (coords->playback_rate != 0.0f) { | if (coords->playback_rate != 0.0f) { | ||||
| float scene_playback_rate = (float)scene->r.frs_sec / scene->r.frs_sec_base; | float video_edit_playback_rate = (float)video_edit->r.frs_sec / video_edit->r.frs_sec_base; | ||||
| strip_len = coords->strip_len / (coords->playback_rate / scene_playback_rate); | strip_len = coords->strip_len / (coords->playback_rate / video_edit_playback_rate); | ||||
| } | } | ||||
| else { | else { | ||||
| strip_len = coords->strip_len; | strip_len = coords->strip_len; | ||||
| } | } | ||||
| end_frame = coords->start_frame + strip_len; | end_frame = coords->start_frame + strip_len; | ||||
| if (coords->use_snapping) { | if (coords->use_snapping) { | ||||
| /* Do snapping via the existing transform code. */ | /* Do snapping via the existing transform code. */ | ||||
| int snap_delta; | int snap_delta; | ||||
| float snap_frame; | float snap_frame; | ||||
| bool valid_snap; | bool valid_snap; | ||||
| valid_snap = ED_transform_snap_sequencer_to_closest_strip_calc( | valid_snap = ED_transform_snap_sequencer_to_closest_strip_calc( | ||||
| scene, region, start_frame, end_frame, &snap_delta, &snap_frame); | video_edit, region, start_frame, end_frame, &snap_delta, &snap_frame); | ||||
| if (valid_snap) { | if (valid_snap) { | ||||
| /* We snapped onto something! */ | /* We snapped onto something! */ | ||||
| start_frame += snap_delta; | start_frame += snap_delta; | ||||
| coords->start_frame = start_frame; | coords->start_frame = start_frame; | ||||
| end_frame = start_frame + strip_len; | end_frame = start_frame + strip_len; | ||||
| coords->snap_point_x = snap_frame; | coords->snap_point_x = snap_frame; | ||||
| } | } | ||||
| else { | else { | ||||
| /* Nothing was snapped to, disable snap drawing. */ | /* Nothing was snapped to, disable snap drawing. */ | ||||
| coords->use_snapping = false; | coords->use_snapping = false; | ||||
| } | } | ||||
| } | } | ||||
| if (strip_len < 1) { | if (strip_len < 1) { | ||||
| /* Only check if there is a strip already under the mouse cursor. */ | /* Only check if there is a strip already under the mouse cursor. */ | ||||
| coords->is_intersecting = find_nearest_seq(scene, ®ion->v2d, &hand, mval); | coords->is_intersecting = find_nearest_seq(video_edit, ®ion->v2d, &hand, mval); | ||||
| } | } | ||||
| else { | else { | ||||
| /* Check if there is a strip that would intersect with the new strip(s). */ | /* Check if there is a strip that would intersect with the new strip(s). */ | ||||
| coords->is_intersecting = false; | coords->is_intersecting = false; | ||||
| Sequence dummy_seq = {.machine = coords->channel, | Sequence dummy_seq = {.machine = coords->channel, | ||||
| .start = coords->start_frame, | .start = coords->start_frame, | ||||
| .len = coords->strip_len, | .len = coords->strip_len, | ||||
| .speed_factor = 1.0f, | .speed_factor = 1.0f, | ||||
| .media_playback_rate = coords->playback_rate, | .media_playback_rate = coords->playback_rate, | ||||
| .flag = SEQ_AUTO_PLAYBACK_RATE}; | .flag = SEQ_AUTO_PLAYBACK_RATE}; | ||||
| Editing *ed = SEQ_editing_ensure(scene); | |||||
| for (int i = 0; i < coords->channel_len && !coords->is_intersecting; i++) { | for (int i = 0; i < coords->channel_len && !coords->is_intersecting; i++) { | ||||
| coords->is_intersecting = SEQ_transform_test_overlap(scene, ed->seqbasep, &dummy_seq); | coords->is_intersecting = SEQ_transform_test_overlap( | ||||
| video_edit, video_edit->seqbasep, &dummy_seq); | |||||
| dummy_seq.machine++; | dummy_seq.machine++; | ||||
| } | } | ||||
| } | } | ||||
| return strip_len; | return strip_len; | ||||
| } | } | ||||
| static void sequencer_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop) | static void sequencer_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop) | ||||
| ▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | if (g_drop_coords.in_use) { | ||||
| RNA_int_set(drop->ptr, "frame_start", g_drop_coords.start_frame); | RNA_int_set(drop->ptr, "frame_start", g_drop_coords.start_frame); | ||||
| RNA_int_set(drop->ptr, "channel", g_drop_coords.channel); | RNA_int_set(drop->ptr, "channel", g_drop_coords.channel); | ||||
| RNA_boolean_set(drop->ptr, "overlap_shuffle_override", true); | RNA_boolean_set(drop->ptr, "overlap_shuffle_override", true); | ||||
| } | } | ||||
| else { | else { | ||||
| /* We are dropped inside the preview region. Put the strip on top of the | /* We are dropped inside the preview region. Put the strip on top of the | ||||
| * current displayed frame. */ | * current displayed frame. */ | ||||
| Scene *scene = CTX_data_scene(C); | VideoEdit *video_edit = CTX_data_video_edit(C); | ||||
| Editing *ed = SEQ_editing_get(scene); | ListBase *seqbase = SEQ_active_seqbase_get(video_edit); | ||||
| ListBase *seqbase = SEQ_active_seqbase_get(ed); | ListBase *channels = SEQ_channels_displayed_get(video_edit); | ||||
| ListBase *channels = SEQ_channels_displayed_get(ed); | |||||
| SpaceSeq *sseq = CTX_wm_space_seq(C); | SpaceSeq *sseq = CTX_wm_space_seq(C); | ||||
| SeqCollection *strips = SEQ_query_rendered_strips( | SeqCollection *strips = SEQ_query_rendered_strips( | ||||
| scene, channels, seqbase, scene->r.cfra, sseq->chanshown); | video_edit, channels, seqbase, video_edit->r.cfra, sseq->chanshown); | ||||
| /* Get the top most strip channel that is in view. */ | /* Get the top most strip channel that is in view. */ | ||||
| Sequence *seq; | Sequence *seq; | ||||
| int max_channel = -1; | int max_channel = -1; | ||||
| SEQ_ITERATOR_FOREACH (seq, strips) { | SEQ_ITERATOR_FOREACH (seq, strips) { | ||||
| max_channel = max_ii(seq->machine, max_channel); | max_channel = max_ii(seq->machine, max_channel); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 193 Lines • ▼ Show 20 Lines | static bool generic_drop_draw_handling(struct wmDropBox *drop) | ||||
| coords->in_use = true; | coords->in_use = true; | ||||
| return false; | return false; | ||||
| } | } | ||||
| typedef struct DropJobData { | typedef struct DropJobData { | ||||
| char path[FILE_MAX]; | char path[FILE_MAX]; | ||||
| bool only_audio; | bool only_audio; | ||||
| float scene_fps; | float video_edit_fps; | ||||
| } DropJobData; | } DropJobData; | ||||
| static void prefetch_data_fn(void *custom_data, | static void prefetch_data_fn(void *custom_data, | ||||
| short *UNUSED(stop), | short *UNUSED(stop), | ||||
| short *UNUSED(do_update), | short *UNUSED(do_update), | ||||
| float *UNUSED(progress)) | float *UNUSED(progress)) | ||||
| { | { | ||||
| DropJobData *job_data = (DropJobData *)custom_data; | DropJobData *job_data = (DropJobData *)custom_data; | ||||
| if (job_data->only_audio) { | if (job_data->only_audio) { | ||||
| #ifdef WITH_AUDASPACE | #ifdef WITH_AUDASPACE | ||||
| /* Get the sound file length */ | /* Get the sound file length */ | ||||
| AUD_Sound *sound = AUD_Sound_file(job_data->path); | AUD_Sound *sound = AUD_Sound_file(job_data->path); | ||||
| if (sound != NULL) { | if (sound != NULL) { | ||||
| AUD_SoundInfo info = AUD_getInfo(sound); | AUD_SoundInfo info = AUD_getInfo(sound); | ||||
| if ((eSoundChannels)info.specs.channels != SOUND_CHANNELS_INVALID) { | if ((eSoundChannels)info.specs.channels != SOUND_CHANNELS_INVALID) { | ||||
| g_drop_coords.strip_len = max_ii(1, round((info.length) * job_data->scene_fps)); | g_drop_coords.strip_len = max_ii(1, round((info.length) * job_data->video_edit_fps)); | ||||
| } | } | ||||
| AUD_Sound_free(sound); | AUD_Sound_free(sound); | ||||
| return; | return; | ||||
| } | } | ||||
| #endif | #endif | ||||
| } | } | ||||
| char colorspace[64] = "\0"; /* 64 == MAX_COLORSPACE_NAME length. */ | char colorspace[64] = "\0"; /* 64 == MAX_COLORSPACE_NAME length. */ | ||||
| Show All 33 Lines | |||||
| static void start_audio_video_job(bContext *C, wmDrag *drag, bool only_audio) | static void start_audio_video_job(bContext *C, wmDrag *drag, bool only_audio) | ||||
| { | { | ||||
| g_drop_coords.strip_len = 0; | g_drop_coords.strip_len = 0; | ||||
| g_drop_coords.channel_len = 1; | g_drop_coords.channel_len = 1; | ||||
| wmWindowManager *wm = CTX_wm_manager(C); | wmWindowManager *wm = CTX_wm_manager(C); | ||||
| wmWindow *win = CTX_wm_window(C); | wmWindow *win = CTX_wm_window(C); | ||||
| Scene *scene = CTX_data_scene(C); | VideoEdit *video_edit = CTX_data_video_edit(C); | ||||
| wmJob *wm_job = WM_jobs_get( | wmJob *wm_job = WM_jobs_get( | ||||
| wm, win, NULL, "Load Previews", 0, WM_JOB_TYPE_SEQ_DRAG_DROP_PREVIEW); | wm, win, NULL, "Load Previews", 0, WM_JOB_TYPE_SEQ_DRAG_DROP_PREVIEW); | ||||
| DropJobData *job_data = (DropJobData *)MEM_mallocN(sizeof(DropJobData), | DropJobData *job_data = (DropJobData *)MEM_mallocN(sizeof(DropJobData), | ||||
| "SeqDragDropPreviewData"); | "SeqDragDropPreviewData"); | ||||
| get_drag_path(drag, job_data->path); | get_drag_path(drag, job_data->path); | ||||
| job_data->only_audio = only_audio; | job_data->only_audio = only_audio; | ||||
| job_data->scene_fps = FPS; | job_data->video_edit_fps = (((double)video_edit->r.frs_sec) / (double)video_edit->r.frs_sec_base); | ||||
| WM_jobs_customdata_set(wm_job, job_data, free_prefetch_data_fn); | WM_jobs_customdata_set(wm_job, job_data, free_prefetch_data_fn); | ||||
| WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW); | WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW); | ||||
| WM_jobs_callbacks(wm_job, prefetch_data_fn, NULL, NULL, NULL); | WM_jobs_callbacks(wm_job, prefetch_data_fn, NULL, NULL, NULL); | ||||
| WM_jobs_start(wm, wm_job); | WM_jobs_start(wm, wm_job); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 159 Lines • Show Last 20 Lines | |||||