diff options
author | Colin Basnett <cmbasnett@gmail.com> | 2022-09-17 03:50:37 +0300 |
---|---|---|
committer | Colin Basnett <cmbasnett@gmail.com> | 2022-09-17 03:50:37 +0300 |
commit | 564bda241a973396da51d7c3ccd9efd97d51728a (patch) | |
tree | 4d9aa4cccd82e2e606b47774afa5e1015bf14768 /source/blender/editors/space_sequencer | |
parent | 0fff238150d076576053c25b646f653d6e3b0edb (diff) | |
parent | 48d7ff68f0df209c77bbb081ab46fbc109fd825a (diff) |
Merge branch 'master' into feature-imformatfeature-imformat
Diffstat (limited to 'source/blender/editors/space_sequencer')
12 files changed, 815 insertions, 696 deletions
diff --git a/source/blender/editors/space_sequencer/CMakeLists.txt b/source/blender/editors/space_sequencer/CMakeLists.txt index 44f919ca361..deaec0136c4 100644 --- a/source/blender/editors/space_sequencer/CMakeLists.txt +++ b/source/blender/editors/space_sequencer/CMakeLists.txt @@ -15,7 +15,6 @@ set(INC ../../sequencer ../../windowmanager ../../../../intern/atomic - ../../../../intern/glew-mx ../../../../intern/guardedalloc # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 647d13a4d56..dd6d58ee5a2 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -85,6 +85,7 @@ typedef struct SequencerAddData { #define SEQPROP_NOCHAN (1 << 3) #define SEQPROP_FIT_METHOD (1 << 4) #define SEQPROP_VIEW_TRANSFORM (1 << 5) +#define SEQPROP_PLAYBACK_RATE (1 << 6) static const EnumPropertyItem scale_fit_methods[] = { {SEQ_SCALE_TO_FIT, "FIT", 0, "Scale to Fit", "Scale image to fit within the canvas"}, @@ -158,6 +159,14 @@ static void sequencer_generic_props__internal(wmOperatorType *ot, int flag) "Set View Transform", "Set appropriate view transform based on media color space"); } + + if (flag & SEQPROP_PLAYBACK_RATE) { + ot->prop = RNA_def_boolean(ot->srna, + "adjust_playback_rate", + true, + "Adjust Playback Rate", + "Play at normal speed regardless of scene FPS"); + } } static void sequencer_generic_invoke_path__internal(bContext *C, @@ -183,7 +192,7 @@ static int sequencer_generic_invoke_xy_guess_channel(bContext *C, int type) Sequence *seq; Scene *scene = CTX_data_scene(C); Editing *ed = SEQ_editing_ensure(scene); - int timeline_frame = (int)CFRA; + int timeline_frame = (int)scene->r.cfra; int proximity = INT_MAX; if (!ed || !ed->seqbasep) { @@ -191,7 +200,7 @@ static int sequencer_generic_invoke_xy_guess_channel(bContext *C, int type) } for (seq = ed->seqbasep->first; seq; seq = seq->next) { - const int strip_end = SEQ_time_right_handle_frame_get(seq); + const int strip_end = SEQ_time_right_handle_frame_get(scene, seq); if ((ELEM(type, -1, seq->type)) && (strip_end < timeline_frame) && (timeline_frame - strip_end < proximity)) { tgt = seq; @@ -209,7 +218,7 @@ static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, i { Scene *scene = CTX_data_scene(C); - int timeline_frame = (int)CFRA; + int timeline_frame = (int)scene->r.cfra; /* Effect strips don't need a channel initialized from the mouse. */ if (!(flag & SEQPROP_NOCHAN) && RNA_struct_property_is_set(op->ptr, "channel") == 0) { @@ -250,6 +259,10 @@ static void load_data_init_from_operator(SeqLoadData *load_data, bContext *C, wm SEQ_tool_settings_fit_method_set(CTX_data_scene(C), load_data->fit_method); } + if ((prop = RNA_struct_find_property(op->ptr, "adjust_playback_rate"))) { + load_data->adjust_playback_rate = RNA_boolean_get(op->ptr, "adjust_playback_rate"); + } + if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) { RNA_property_string_get(op->ptr, prop, load_data->path); BLI_strncpy(load_data->name, BLI_path_basename(load_data->path), sizeof(load_data->name)); @@ -327,7 +340,7 @@ static void seq_load_apply_generic_options(bContext *C, wmOperator *op, Sequence } if (RNA_boolean_get(op->ptr, "overlap") == true || - !SEQ_transform_test_overlap(ed->seqbasep, seq)) { + !SEQ_transform_test_overlap(scene, ed->seqbasep, seq)) { /* No overlap should be handled or the strip is not overlapping, exit early. */ return; } @@ -370,7 +383,7 @@ static bool seq_load_apply_generic_options_only_test_overlap(bContext *C, SEQ_collection_append_strip(seq, strip_col); - return SEQ_transform_test_overlap(ed->seqbasep, seq); + return SEQ_transform_test_overlap(scene, ed->seqbasep, seq); } static bool seq_effect_add_properties_poll(const bContext *UNUSED(C), @@ -793,8 +806,10 @@ static void sequencer_add_movie_clamp_sound_strip_length(Scene *scene, return; } - SEQ_time_right_handle_frame_set(scene, seq_sound, SEQ_time_right_handle_frame_get(seq_movie)); - SEQ_time_left_handle_frame_set(scene, seq_sound, SEQ_time_left_handle_frame_get(seq_movie)); + SEQ_time_right_handle_frame_set( + scene, seq_sound, SEQ_time_right_handle_frame_get(scene, seq_movie)); + SEQ_time_left_handle_frame_set( + scene, seq_sound, SEQ_time_left_handle_frame_get(scene, seq_movie)); } static void sequencer_add_movie_multiple_strips(bContext *C, @@ -841,8 +856,8 @@ static void sequencer_add_movie_multiple_strips(bContext *C, } } - load_data->start_frame += SEQ_time_right_handle_frame_get(seq_movie) - - SEQ_time_left_handle_frame_get(seq_movie); + load_data->start_frame += SEQ_time_right_handle_frame_get(scene, seq_movie) - + SEQ_time_left_handle_frame_get(scene, seq_movie); if (overlap_shuffle_override) { has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap( C, op, seq_sound, strip_col); @@ -976,6 +991,7 @@ static int sequencer_add_movie_strip_invoke(bContext *C, sequencer_disable_one_time_properties(C, op); RNA_enum_set(op->ptr, "fit_method", SEQ_tool_settings_fit_method_get(scene)); + RNA_boolean_set(op->ptr, "adjust_playback_rate", true); /* This is for drag and drop. */ if ((RNA_struct_property_is_set(op->ptr, "files") && @@ -1042,8 +1058,9 @@ void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot) WM_FILESEL_SHOW_PROPS | WM_FILESEL_DIRECTORY, FILE_DEFAULTDISPLAY, FILE_SORT_DEFAULT); - sequencer_generic_props__internal( - ot, SEQPROP_STARTFRAME | SEQPROP_FIT_METHOD | SEQPROP_VIEW_TRANSFORM); + sequencer_generic_props__internal(ot, + SEQPROP_STARTFRAME | SEQPROP_FIT_METHOD | + SEQPROP_VIEW_TRANSFORM | SEQPROP_PLAYBACK_RATE); RNA_def_boolean(ot->srna, "sound", true, "Sound", "Load sound with the movie"); RNA_def_boolean(ot->srna, "use_framerate", @@ -1073,8 +1090,8 @@ static void sequencer_add_sound_multiple_strips(bContext *C, } else { seq_load_apply_generic_options(C, op, seq); - load_data->start_frame += SEQ_time_right_handle_frame_get(seq) - - SEQ_time_left_handle_frame_get(seq); + load_data->start_frame += SEQ_time_right_handle_frame_get(scene, seq) - + SEQ_time_left_handle_frame_get(scene, seq); } } RNA_END; @@ -1250,8 +1267,12 @@ static int sequencer_add_image_strip_calculate_length(wmOperator *op, return RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files")); } -static void sequencer_add_image_strip_load_files( - wmOperator *op, Sequence *seq, SeqLoadData *load_data, const int minframe, const int numdigits) +static void sequencer_add_image_strip_load_files(wmOperator *op, + Scene *scene, + Sequence *seq, + SeqLoadData *load_data, + const int minframe, + const int numdigits) { const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders"); /* size of Strip->dir. */ @@ -1267,7 +1288,7 @@ static void sequencer_add_image_strip_load_files( size_t strip_frame = 0; RNA_BEGIN (op->ptr, itemptr, "files") { char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0, NULL); - SEQ_add_image_load_file(seq, strip_frame, filename); + SEQ_add_image_load_file(scene, seq, strip_frame, filename); MEM_freeN(filename); strip_frame++; } @@ -1296,7 +1317,7 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) } Sequence *seq = SEQ_add_image_strip(CTX_data_main(C), scene, ed->seqbasep, &load_data); - sequencer_add_image_strip_load_files(op, seq, &load_data, minframe, numdigits); + sequencer_add_image_strip_load_files(op, scene, seq, &load_data, minframe, numdigits); SEQ_add_image_init_alpha_mode(seq); /* Adjust length. */ diff --git a/source/blender/editors/space_sequencer/sequencer_channels_draw.c b/source/blender/editors/space_sequencer/sequencer_channels_draw.c index c11388e8555..81fc87598f8 100644 --- a/source/blender/editors/space_sequencer/sequencer_channels_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_channels_draw.c @@ -97,7 +97,7 @@ static void displayed_channel_range_get(const SeqChannelDrawContext *context, rctf strip_boundbox; BLI_rctf_init(&strip_boundbox, 0.0f, 0.0f, 1.0f, r_channel_range[1]); - SEQ_timeline_expand_boundbox(context->seqbase, &strip_boundbox); + SEQ_timeline_expand_boundbox(context->scene, context->seqbase, &strip_boundbox); CLAMP(r_channel_range[0], strip_boundbox.ymin, strip_boundbox.ymax); CLAMP(r_channel_range[1], strip_boundbox.ymin, MAXSEQ); } diff --git a/source/blender/editors/space_sequencer/sequencer_drag_drop.c b/source/blender/editors/space_sequencer/sequencer_drag_drop.c index 8dadb9360e3..c892e7d7e55 100644 --- a/source/blender/editors/space_sequencer/sequencer_drag_drop.c +++ b/source/blender/editors/space_sequencer/sequencer_drag_drop.c @@ -51,7 +51,9 @@ typedef struct SeqDropCoords { float start_frame, channel; int strip_len, channel_len; + float playback_rate; bool in_use; + bool has_read_mouse_pos; bool is_intersecting; bool use_snapping; float snap_point_x; @@ -63,7 +65,7 @@ typedef struct SeqDropCoords { * preloading data on drag start. * Therefore we will for now use a global variable for this. */ -static SeqDropCoords g_drop_coords = {.in_use = false}; +static SeqDropCoords g_drop_coords = {.in_use = false, .has_read_mouse_pos = false}; static void generic_poll_operations(const wmEvent *event, uint8_t type) { @@ -82,31 +84,134 @@ static bool image_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *ev } } - return WM_drag_is_ID_type(drag, ID_IM); + if (WM_drag_is_ID_type(drag, ID_IM)) { + generic_poll_operations(event, TH_SEQ_IMAGE); + return true; + } + + return false; } -static bool movie_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *event) +static bool is_movie(wmDrag *drag) { if (drag->type == WM_DRAG_PATH) { - if (ELEM(drag->icon, 0, ICON_FILE_MOVIE, ICON_FILE_BLANK)) { /* Rule might not work? */ - generic_poll_operations(event, TH_SEQ_MOVIE); + if (ELEM(drag->icon, ICON_FILE_MOVIE, ICON_FILE_BLANK)) { /* Rule might not work? */ return true; } } + if (WM_drag_is_ID_type(drag, ID_MC)) { + return true; + } + return false; +} + +static bool movie_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *event) +{ + if (is_movie(drag)) { + generic_poll_operations(event, TH_SEQ_MOVIE); + return true; + } - return WM_drag_is_ID_type(drag, ID_MC); + return false; } -static bool sound_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *event) +static bool is_sound(wmDrag *drag) { if (drag->type == WM_DRAG_PATH) { if (ELEM(drag->icon, ICON_FILE_SOUND, ICON_FILE_BLANK)) { /* Rule might not work? */ - generic_poll_operations(event, TH_SEQ_AUDIO); return true; } } + if (WM_drag_is_ID_type(drag, ID_SO)) { + return true; + } + return false; +} - return WM_drag_is_ID_type(drag, ID_SO); +static bool sound_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *event) +{ + if (is_sound(drag)) { + generic_poll_operations(event, TH_SEQ_AUDIO); + return true; + } + + return false; +} + +static float update_overlay_strip_position_data(bContext *C, const int mval[2]) +{ + SeqDropCoords *coords = &g_drop_coords; + ARegion *region = CTX_wm_region(C); + Scene *scene = CTX_data_scene(C); + int hand; + View2D *v2d = ®ion->v2d; + + /* 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); + coords->start_frame = roundf(coords->start_frame); + if (coords->channel < 1.0f) { + coords->channel = 1; + } + + float start_frame = coords->start_frame; + float end_frame; + float strip_len; + + if (coords->playback_rate != 0.0f) { + float scene_playback_rate = (float)scene->r.frs_sec / scene->r.frs_sec_base; + strip_len = coords->strip_len / (coords->playback_rate / scene_playback_rate); + } + else { + strip_len = coords->strip_len; + } + + end_frame = coords->start_frame + strip_len; + + if (coords->use_snapping) { + /* Do snapping via the existing transform code. */ + int snap_delta; + float snap_frame; + bool valid_snap; + + valid_snap = ED_transform_snap_sequencer_to_closest_strip_calc( + scene, region, start_frame, end_frame, &snap_delta, &snap_frame); + + if (valid_snap) { + /* We snapped onto something! */ + start_frame += snap_delta; + coords->start_frame = start_frame; + end_frame = start_frame + strip_len; + coords->snap_point_x = snap_frame; + } + else { + /* Nothing was snapped to, disable snap drawing. */ + coords->use_snapping = false; + } + } + + if (strip_len < 1) { + /* Only check if there is a strip already under the mouse cursor. */ + coords->is_intersecting = find_nearest_seq(scene, ®ion->v2d, &hand, mval); + } + else { + /* Check if there is a strip that would intersect with the new strip(s). */ + coords->is_intersecting = false; + Sequence dummy_seq = {.machine = coords->channel, + .start = coords->start_frame, + .len = coords->strip_len, + .speed_factor = 1.0f, + .media_playback_rate = coords->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++) { + coords->is_intersecting = SEQ_transform_test_overlap(scene, ed->seqbasep, &dummy_seq); + dummy_seq.machine++; + } + } + + return strip_len; } static void sequencer_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop) @@ -153,92 +258,77 @@ static void sequencer_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop) RNA_collection_add(drop->ptr, "files", &itemptr); RNA_string_set(&itemptr, "name", file); } - - if (g_drop_coords.in_use) { - RNA_int_set(drop->ptr, "frame_start", g_drop_coords.start_frame); - RNA_int_set(drop->ptr, "channel", g_drop_coords.channel); - RNA_boolean_set(drop->ptr, "overlap_shuffle_override", true); - } - else { - Scene *scene = CTX_data_scene(C); - Editing *ed = SEQ_editing_get(scene); - ListBase *seqbase = SEQ_active_seqbase_get(ed); - ListBase *channels = SEQ_channels_displayed_get(ed); - SpaceSeq *sseq = CTX_wm_space_seq(C); - - SeqCollection *strips = SEQ_query_rendered_strips( - channels, seqbase, scene->r.cfra, sseq->chanshown); - - /* Get the top most strip channel that is in view.*/ - Sequence *seq; - int max_channel = -1; - SEQ_ITERATOR_FOREACH (seq, strips) { - max_channel = max_ii(seq->machine, max_channel); - } - - if (max_channel != -1) { - RNA_int_set(drop->ptr, "channel", max_channel); - } - } } -} -static void update_overlay_strip_poistion_data(bContext *C, const int mval[2]) -{ - SeqDropCoords *coords = &g_drop_coords; - ARegion *region = CTX_wm_region(C); - Scene *scene = CTX_data_scene(C); - int hand; - View2D *v2d = ®ion->v2d; + if (g_drop_coords.in_use) { + if (!g_drop_coords.has_read_mouse_pos) { + /* We didn't read the mouse position, so we need to do it manually here. */ + int xy[2]; + wmWindow *win = CTX_wm_window(C); + xy[0] = win->eventstate->xy[0]; + xy[1] = win->eventstate->xy[1]; + + ARegion *region = CTX_wm_region(C); + int mval[2]; + /* Convert mouse coordinates to region local coordinates. */ + mval[0] = xy[0] - region->winrct.xmin; + mval[1] = xy[1] - region->winrct.ymin; + + update_overlay_strip_position_data(C, mval); + } - /* 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); - coords->start_frame = roundf(coords->start_frame); - if (coords->channel < 1.0f) { - coords->channel = 1; + RNA_int_set(drop->ptr, "frame_start", g_drop_coords.start_frame); + RNA_int_set(drop->ptr, "channel", g_drop_coords.channel); + RNA_boolean_set(drop->ptr, "overlap_shuffle_override", true); } + else { + /* We are dropped inside the preview region. Put the strip on top of the + * current displayed frame. */ + Scene *scene = CTX_data_scene(C); + Editing *ed = SEQ_editing_get(scene); + ListBase *seqbase = SEQ_active_seqbase_get(ed); + ListBase *channels = SEQ_channels_displayed_get(ed); + SpaceSeq *sseq = CTX_wm_space_seq(C); - float start_frame = coords->start_frame; - float end_frame = coords->start_frame + coords->strip_len; - - if (coords->use_snapping) { - /* Do snapping via the existing transform code. */ - int snap_delta; - float snap_frame; - bool valid_snap; + SeqCollection *strips = SEQ_query_rendered_strips( + scene, channels, seqbase, scene->r.cfra, sseq->chanshown); - valid_snap = ED_transform_snap_sequencer_to_closest_strip_calc( - scene, region, start_frame, end_frame, &snap_delta, &snap_frame); - - if (valid_snap) { - /* We snapped onto something! */ - start_frame += snap_delta; - coords->start_frame = start_frame; - end_frame = start_frame + coords->strip_len; - coords->snap_point_x = snap_frame; + /* Get the top most strip channel that is in view. */ + Sequence *seq; + int max_channel = -1; + SEQ_ITERATOR_FOREACH (seq, strips) { + max_channel = max_ii(seq->machine, max_channel); } - else { - /* Nothing was snapped to, disable snap drawing. */ - coords->use_snapping = false; + + if (max_channel != -1) { + RNA_int_set(drop->ptr, "channel", max_channel); } + SEQ_collection_free(strips); } +} - if (coords->strip_len < 1) { - /* Only check if there is a strip already under the mouse cursor. */ - coords->is_intersecting = find_nearest_seq(scene, ®ion->v2d, &hand, mval); +static void get_drag_path(wmDrag *drag, char r_path[FILE_MAX]) +{ + ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0); + /* ID dropped. */ + if (id != NULL) { + const ID_Type id_type = GS(id->name); + if (id_type == ID_IM) { + Image *ima = (Image *)id; + BLI_strncpy(r_path, ima->filepath, FILE_MAX); + } + else if (id_type == ID_MC) { + MovieClip *clip = (MovieClip *)id; + BLI_strncpy(r_path, clip->filepath, FILE_MAX); + } + else if (id_type == ID_SO) { + bSound *sound = (bSound *)id; + BLI_strncpy(r_path, sound->filepath, FILE_MAX); + } + BLI_path_abs(r_path, BKE_main_blendfile_path_from_global()); } else { - /* Check if there is a strip that would intersect with the new strip(s). */ - coords->is_intersecting = false; - Sequence dummy_seq = { - .machine = coords->channel, .start = coords->start_frame, .len = coords->strip_len}; - Editing *ed = SEQ_editing_get(scene); - - for (int i = 0; i < coords->channel_len && !coords->is_intersecting; i++) { - coords->is_intersecting = SEQ_transform_test_overlap(ed->seqbasep, &dummy_seq); - dummy_seq.machine++; - } + BLI_strncpy(r_path, drag->path, FILE_MAX); } } @@ -255,7 +345,7 @@ static void draw_seq_in_view(bContext *C, wmWindow *UNUSED(win), wmDrag *drag, c mval[0] = xy[0] - region->winrct.xmin; mval[1] = xy[1] - region->winrct.ymin; - update_overlay_strip_poistion_data(C, mval); + float strip_len = update_overlay_strip_position_data(C, mval); GPU_matrix_push(); UI_view2d_view_ortho(®ion->v2d); @@ -275,11 +365,11 @@ static void draw_seq_in_view(bContext *C, wmWindow *UNUSED(win), wmDrag *drag, c GPU_blend(GPU_BLEND_ALPHA); GPU_line_smooth(true); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* Draw strips. The code here is taken from sequencer_draw. */ float x1 = coords->start_frame; - float x2 = coords->start_frame + coords->strip_len; + float x2 = coords->start_frame + floorf(strip_len); float strip_color[3]; uchar text_color[4] = {255, 255, 255, 255}; float pixelx = BLI_rctf_size_x(®ion->v2d.cur) / BLI_rcti_size_x(®ion->v2d.mask); @@ -353,21 +443,22 @@ static void draw_seq_in_view(bContext *C, wmWindow *UNUSED(win), wmDrag *drag, c const char *text_array[5]; char text_display[FILE_MAX]; char filename[FILE_MAX]; - char rel_path[FILE_MAX]; + char path[FILE_MAX]; char strip_duration_text[16]; int len_text_arr = 0; + get_drag_path(drag, path); + if (sseq->timeline_overlay.flag & SEQ_TIMELINE_SHOW_STRIP_NAME) { - BLI_split_file_part(drag->path, filename, FILE_MAX); + BLI_split_file_part(path, filename, FILE_MAX); text_array[len_text_arr++] = filename; } if (sseq->timeline_overlay.flag & SEQ_TIMELINE_SHOW_STRIP_SOURCE) { Main *bmain = CTX_data_main(C); - BLI_strncpy(rel_path, drag->path, FILE_MAX); - BLI_path_rel(rel_path, BKE_main_blendfile_path(bmain)); + BLI_path_rel(path, BKE_main_blendfile_path(bmain)); text_array[len_text_arr++] = text_sep; - text_array[len_text_arr++] = rel_path; + text_array[len_text_arr++] = path; } if (sseq->timeline_overlay.flag & SEQ_TIMELINE_SHOW_STRIP_DURATION) { @@ -441,6 +532,14 @@ static void prefetch_data_fn(void *custom_data, if (anim != NULL) { g_drop_coords.strip_len = IMB_anim_get_duration(anim, IMB_TC_NONE); + short frs_sec; + float frs_sec_base; + if (IMB_anim_get_fps(anim, &frs_sec, &frs_sec_base, true)) { + g_drop_coords.playback_rate = (float)frs_sec / frs_sec_base; + } + else { + g_drop_coords.playback_rate = 0; + } IMB_free_anim(anim); #ifdef WITH_AUDASPACE /* Try to load sound and see if the video has a sound channel. */ @@ -463,7 +562,7 @@ static void free_prefetch_data_fn(void *custom_data) MEM_freeN(job_data); } -static void start_audio_video_job(bContext *C, char *path, 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.channel_len = 1; @@ -477,8 +576,8 @@ static void start_audio_video_job(bContext *C, char *path, bool only_audio) DropJobData *job_data = (DropJobData *)MEM_mallocN(sizeof(DropJobData), "SeqDragDropPreviewData"); + get_drag_path(drag, job_data->path); - BLI_strncpy(job_data->path, path, FILE_MAX); job_data->only_audio = only_audio; job_data->scene_fps = FPS; @@ -491,15 +590,15 @@ static void start_audio_video_job(bContext *C, char *path, bool only_audio) static void video_prefetch(bContext *C, wmDrag *drag) { - if (drag->type == WM_DRAG_PATH && ELEM(drag->icon, ICON_FILE_MOVIE, ICON_FILE_BLANK)) { - start_audio_video_job(C, drag->path, false); + if (is_movie(drag)) { + start_audio_video_job(C, drag, false); } } static void audio_prefetch(bContext *C, wmDrag *drag) { - if (drag->type == WM_DRAG_PATH && ELEM(drag->icon, ICON_FILE_SOUND, ICON_FILE_BLANK)) { - start_audio_video_job(C, drag->path, true); + if (is_sound(drag)) { + start_audio_video_job(C, drag, true); } } @@ -533,6 +632,7 @@ static void sequencer_drop_draw_deactivate(struct wmDropBox *drop, wmDrag *UNUSE SeqDropCoords *coords = drop->draw_data; if (coords) { coords->in_use = false; + coords->has_read_mouse_pos = false; drop->draw_data = NULL; } } diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 25701c323b9..71804d29e6b 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -241,327 +241,282 @@ typedef struct WaveVizData { float pos[2]; float rms_pos; bool clip; - bool end; + bool draw_line; /* Draw triangle otherwise. */ + bool final_sample; /* There are no more samples. */ } WaveVizData; -static int get_section_len(WaveVizData *start, WaveVizData *end) +static bool seq_draw_waveforms_poll(const bContext *UNUSED(C), SpaceSeq *sseq, Sequence *seq) { - int len = 0; - while (start != end) { - len++; - if (start->end) { - return len; - } - start++; - } - return len; -} + const bool strip_is_valid = seq->type == SEQ_TYPE_SOUND_RAM && seq->sound != NULL; + const bool overlays_enabled = (sseq->flag & SEQ_SHOW_OVERLAY) != 0; + const bool ovelay_option = ((sseq->timeline_overlay.flag & SEQ_TIMELINE_ALL_WAVEFORMS) != 0 || + (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM)); -static void draw_waveform(WaveVizData *iter, WaveVizData *end, GPUPrimType prim_type, bool use_rms) -{ - int strip_len = get_section_len(iter, end); - if (strip_len > 1) { - GPU_blend(GPU_BLEND_ALPHA); - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + if ((sseq->timeline_overlay.flag & SEQ_TIMELINE_NO_WAVEFORMS) != 0) { + return false; + } - immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); - immBegin(prim_type, strip_len); + if (strip_is_valid && overlays_enabled && ovelay_option) { + return true; + } - while (iter != end) { - if (iter->clip) { - immAttr4f(col, 1.0f, 0.0f, 0.0f, 0.5f); - } - else if (use_rms) { - immAttr4f(col, 1.0f, 1.0f, 1.0f, 0.8f); - } - else { - immAttr4f(col, 1.0f, 1.0f, 1.0f, 0.5f); - } + return false; +} - if (use_rms) { - immVertex2f(pos, iter->pos[0], iter->rms_pos); - } - else { - immVertex2f(pos, iter->pos[0], iter->pos[1]); - } +static void waveform_job_start_if_needed(const bContext *C, Sequence *seq) +{ + bSound *sound = seq->sound; - if (iter->end) { - /* End of line. */ - iter++; - strip_len = get_section_len(iter, end); - if (strip_len != 0) { - immEnd(); - immUnbindProgram(); - immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); - immBegin(prim_type, strip_len); - } - } - else { - iter++; - } + BLI_spin_lock(sound->spinlock); + if (!sound->waveform) { + /* Load the waveform data if it hasn't been loaded and cached already. */ + if (!(sound->tags & SOUND_TAGS_WAVEFORM_LOADING)) { + /* Prevent sounds from reloading. */ + sound->tags |= SOUND_TAGS_WAVEFORM_LOADING; + BLI_spin_unlock(sound->spinlock); + sequencer_preview_add_sound(C, seq); + } + else { + BLI_spin_unlock(sound->spinlock); } - immEnd(); - immUnbindProgram(); - - GPU_blend(GPU_BLEND_NONE); } + BLI_spin_unlock(sound->spinlock); } -static float clamp_frame_coord_to_pixel(float frame_coord, - float pixel_frac, - float frames_per_pixel) +static size_t get_vertex_count(WaveVizData *waveform_data) { - float cur_pixel = (frame_coord / frames_per_pixel); - float new_pixel = (int)(frame_coord / frames_per_pixel) + pixel_frac; - if (cur_pixel > new_pixel) { - new_pixel += 1.0f; + bool draw_line = waveform_data->draw_line; + size_t length = 0; + + while (waveform_data->draw_line == draw_line && !waveform_data->final_sample) { + waveform_data++; + length++; } - return new_pixel * frames_per_pixel; + + return length; } -/** - * \param x1, x2, y1, y2: The starting and end X value to draw the wave, same for y1 and y2. - * \param frames_per_pixel: The amount of pixels a whole frame takes up (x-axis direction). - */ -static void draw_seq_waveform_overlay(View2D *v2d, - const bContext *C, - SpaceSeq *sseq, - Scene *scene, - Sequence *seq, - float x1, - float y1, - float x2, - float y2, - float frames_per_pixel) +static size_t draw_waveform_segment(WaveVizData *waveform_data, bool use_rms) { - if (seq->sound && ((sseq->timeline_overlay.flag & SEQ_TIMELINE_ALL_WAVEFORMS) || - (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM))) { - /* Make sure that the start drawing position is aligned to the pixels on the screen to avoid - * flickering when moving around the strip. - * To do this we figure out the fractional offset in pixel space by checking where the - * window starts. - * We then append this pixel offset to our strip start coordinate to ensure we are aligned to - * the screen pixel grid. */ - float pixel_frac = v2d->cur.xmin / frames_per_pixel - floor(v2d->cur.xmin / frames_per_pixel); - float x1_adj = clamp_frame_coord_to_pixel(x1, pixel_frac, frames_per_pixel); - - /* Offset x1 and x2 values, to match view min/max, if strip is out of bounds. */ - float x1_offset = max_ff(v2d->cur.xmin, x1_adj); - float x2_offset = min_ff(v2d->cur.xmax, x2); - - /* Calculate how long the strip that is in view is in pixels. */ - int pix_strip_len = round((x2_offset - x1_offset) / frames_per_pixel); - - if (pix_strip_len < 2) { - return; - } + size_t vertices_done = 0; + size_t vertex_count = get_vertex_count(waveform_data); - bSound *sound = seq->sound; + /* Not enough data to draw. */ + if (vertex_count <= 2) { + return vertex_count; + } - BLI_spin_lock(sound->spinlock); - if (!sound->waveform) { - /* Load the waveform data if it hasn't been loaded and cached already. */ - if (!(sound->tags & SOUND_TAGS_WAVEFORM_LOADING)) { - /* Prevent sounds from reloading. */ - sound->tags |= SOUND_TAGS_WAVEFORM_LOADING; - BLI_spin_unlock(sound->spinlock); - sequencer_preview_add_sound(C, seq); - } - else { - BLI_spin_unlock(sound->spinlock); - } - return; /* Nothing to draw. */ - } - BLI_spin_unlock(sound->spinlock); + GPU_blend(GPU_BLEND_ALPHA); + GPUVertFormat *format = immVertexFormat(); + GPUPrimType prim_type = waveform_data->draw_line ? GPU_PRIM_LINE_STRIP : GPU_PRIM_TRI_STRIP; + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + immBegin(prim_type, vertex_count); - SoundWaveform *waveform = sound->waveform; + while (vertices_done < vertex_count && !waveform_data->final_sample) { + /* Color. */ + if (waveform_data->clip) { + immAttr4f(col, 1.0f, 0.0f, 0.0f, 0.5f); + } + else if (use_rms) { + immAttr4f(col, 1.0f, 1.0f, 1.0f, 0.8f); + } + else { + immAttr4f(col, 1.0f, 1.0f, 1.0f, 0.5f); + } - /* Waveform could not be built. */ - if (waveform->length == 0) { - return; + /* Vertices. */ + if (use_rms) { + immVertex2f(pos, waveform_data->pos[0], waveform_data->rms_pos); + } + else { + immVertex2f(pos, waveform_data->pos[0], waveform_data->pos[1]); } - /* F-Curve lookup is quite expensive, so do this after precondition. */ - FCurve *fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "volume", 0, NULL); + vertices_done++; + waveform_data++; + } - WaveVizData *tri_strip_arr = MEM_callocN(sizeof(*tri_strip_arr) * pix_strip_len * 2, - "tri_strip"); - WaveVizData *line_strip_arr = MEM_callocN(sizeof(*line_strip_arr) * pix_strip_len, - "line_strip"); + immEnd(); + immUnbindProgram(); - WaveVizData *tri_strip_iter = tri_strip_arr; - WaveVizData *line_strip_iter = line_strip_arr; + GPU_blend(GPU_BLEND_NONE); - /* The y coordinate for the middle of the strip. */ - float y_mid = (y1 + y2) / 2.0f; - /* The length from the middle of the strip to the top/bottom. */ - float y_scale = (y2 - y1) / 2.0f; - float volume = seq->volume; + return vertices_done; +} - /* Value to keep track if the previous item to be drawn was a line strip. */ - int8_t was_line_strip = -1; /* -1 == no previous value. */ +static void draw_waveform(WaveVizData *waveform_data, size_t wave_data_len) +{ + size_t items_done = 0; + while (items_done < wave_data_len) { + if (!waveform_data[items_done].draw_line) { /* Draw RMS. */ + draw_waveform_segment(&waveform_data[items_done], true); + } + items_done += draw_waveform_segment(&waveform_data[items_done], false); + } +} - float samples_per_frame = SOUND_WAVE_SAMPLES_PER_SECOND / FPS; +static float align_frame_with_pixel(float frame_coord, float frames_per_pixel) +{ + return round_fl_to_int(frame_coord / frames_per_pixel) * frames_per_pixel; +} - /* How many samples do we have for each pixel? */ - float samples_per_pix = samples_per_frame * frames_per_pixel; +static void write_waveform_data(WaveVizData *waveform_data, + const vec2f pos, + const float rms, + const bool is_clipping, + const bool draw_line) +{ + waveform_data->pos[0] = pos.x; + waveform_data->pos[1] = pos.y; + waveform_data->clip = is_clipping; + waveform_data->rms_pos = rms; + waveform_data->draw_line = draw_line; +} - float strip_start_offset = seq->startofs + seq->anim_startofs; - float start_sample = 0; +static size_t waveform_append_sample(WaveVizData *waveform_data, + vec2f pos, + const float value_min, + const float value_max, + const float y_mid, + const float y_scale, + const float rms, + const bool is_clipping, + const bool is_line_strip) +{ + size_t data_written = 0; + pos.y = y_mid + value_min * y_scale; + float rms_value = y_mid + max_ff(-rms, value_min) * y_scale; + write_waveform_data(&waveform_data[0], pos, rms_value, is_clipping, is_line_strip); + data_written++; + + /* Use `value_max` as second vertex for triangle drawing. */ + if (!is_line_strip) { + pos.y = y_mid + value_max * y_scale; + rms_value = y_mid + min_ff(rms, value_max) * y_scale; + write_waveform_data(&waveform_data[1], pos, rms_value, is_clipping, is_line_strip); + data_written++; + } + return data_written; +} - if (strip_start_offset != 0) { - /* If start offset is not zero, we need to make sure that we pick the same start sample as if - * we simply scrolled the start of the strip off-screen. Otherwise we will get flickering - * when changing start offset as the pixel alignment will not be the same for the drawn - * samples. */ - strip_start_offset = clamp_frame_coord_to_pixel( - x1 - strip_start_offset, pixel_frac, frames_per_pixel); - start_sample = fabsf(strip_start_offset - x1_adj) * samples_per_frame; - } +/** + * \param x1, x2, y1, y2: The starting and end X value to draw the wave, same for y1 and y2. + * \param frames_per_pixel: The amount of pixels a whole frame takes up (x-axis direction). + */ +static void draw_seq_waveform_overlay( + const bContext *C, ARegion *region, Sequence *seq, float x1, float y1, float x2, float y2) +{ + const View2D *v2d = ®ion->v2d; + Scene *scene = CTX_data_scene(C); - start_sample += seq->sound->offset_time * SOUND_WAVE_SAMPLES_PER_SECOND; - /* If we scrolled the start off-screen, then the start sample should be at the first visible - * sample. */ - start_sample += (x1_offset - x1_adj) * samples_per_frame; + const float frames_per_pixel = BLI_rctf_size_x(®ion->v2d.cur) / region->winx; + const float samples_per_frame = SOUND_WAVE_SAMPLES_PER_SECOND / FPS; + float samples_per_pixel = samples_per_frame * frames_per_pixel; - for (int i = 0; i < pix_strip_len; i++) { - float sample_offset = start_sample + i * samples_per_pix; - int p = sample_offset; + /* Align strip start with nearest pixel to prevent waveform flickering. */ + const float x1_aligned = align_frame_with_pixel(x1, frames_per_pixel); + /* Offset x1 and x2 values, to match view min/max, if strip is out of bounds. */ + const float frame_start = max_ff(v2d->cur.xmin, x1_aligned); + const float frame_end = min_ff(v2d->cur.xmax, x2); + const int pixels_to_draw = round_fl_to_int((frame_end - frame_start) / frames_per_pixel); - if (p < 0) { - continue; - } + if (pixels_to_draw < 2) { + return; /* Not much to draw, exit before running job. */ + } - if (p >= waveform->length) { - break; - } + waveform_job_start_if_needed(C, seq); - float value_min = waveform->data[p * 3]; - float value_max = waveform->data[p * 3 + 1]; - float rms = waveform->data[p * 3 + 2]; - - if (p + 1 < waveform->length) { - /* Use simple linear interpolation. */ - float f = sample_offset - p; - value_min = (1.0f - f) * value_min + f * waveform->data[p * 3 + 3]; - value_max = (1.0f - f) * value_max + f * waveform->data[p * 3 + 4]; - rms = (1.0f - f) * rms + f * waveform->data[p * 3 + 5]; - if (samples_per_pix > 1.0f) { - /* We need to sum up the values we skip over until the next step. */ - float next_pos = sample_offset + samples_per_pix; - int end_idx = next_pos; - - for (int j = p + 1; (j < waveform->length) && (j < end_idx); j++) { - value_min = min_ff(value_min, waveform->data[j * 3]); - value_max = max_ff(value_max, waveform->data[j * 3 + 1]); - rms = max_ff(rms, waveform->data[j * 3 + 2]); - } - } - } + SoundWaveform *waveform = seq->sound->waveform; + if (waveform == NULL || waveform->length == 0) { + return; /* Waveform was not built. */ + } - if (fcu && !BKE_fcurve_is_empty(fcu)) { - float evaltime = x1_offset + (i * frames_per_pixel); - volume = evaluate_fcurve(fcu, evaltime); - CLAMP_MIN(volume, 0.0f); - } + /* F-Curve lookup is quite expensive, so do this after precondition. */ + FCurve *fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "volume", 0, NULL); + WaveVizData *waveform_data = MEM_callocN(sizeof(WaveVizData) * pixels_to_draw * 3, __func__); + size_t wave_data_len = 0; - value_min *= volume; - value_max *= volume; - rms *= volume; + /* Offset must be also aligned, otherwise waveform flickers when moving left handle. */ + const float strip_offset = align_frame_with_pixel(seq->startofs + seq->anim_startofs, + frames_per_pixel); + float start_sample = strip_offset * samples_per_frame; + start_sample += seq->sound->offset_time * SOUND_WAVE_SAMPLES_PER_SECOND; + /* Add off-screen part of strip to offset. */ + start_sample += (frame_start - x1_aligned) * samples_per_frame; - bool clipping = false; + for (int i = 0; i < pixels_to_draw; i++) { + float sample = start_sample + i * samples_per_pixel; + int sample_index = round_fl_to_int(sample); - if (value_max > 1 || value_min < -1) { - clipping = true; + if (sample_index < 0) { + continue; + } - CLAMP_MAX(value_max, 1.0f); - CLAMP_MIN(value_min, -1.0f); - } + if (sample_index >= waveform->length) { + break; + } - bool is_line_strip = (value_max - value_min < 0.05f); - - if (!ELEM(was_line_strip, -1, is_line_strip)) { - /* If the previously added strip type isn't the same as the current one, - * add transition areas so they transition smoothly between each other. */ - if (is_line_strip) { - /* This will be a line strip, end the tri strip. */ - tri_strip_iter->pos[0] = x1_offset + i * frames_per_pixel; - tri_strip_iter->pos[1] = y_mid + value_min * y_scale; - tri_strip_iter->clip = clipping; - tri_strip_iter->rms_pos = tri_strip_iter->pos[1]; - tri_strip_iter->end = true; - - /* End of section. */ - tri_strip_iter++; - - /* Check if we are at the end. - * If so, skip one point line. */ - if (i + 1 == pix_strip_len) { - continue; - } - } - else { - /* This will be a tri strip. */ - line_strip_iter--; - tri_strip_iter->pos[0] = line_strip_iter->pos[0]; - tri_strip_iter->pos[1] = line_strip_iter->pos[1]; - tri_strip_iter->clip = line_strip_iter->clip; - tri_strip_iter->rms_pos = line_strip_iter->pos[1]; - tri_strip_iter++; - - /* Check if line had only one point. */ - line_strip_iter--; - if (line_strip_iter < line_strip_arr || line_strip_iter->end) { - /* Only one point, skip it. */ - line_strip_iter++; - } - else { - /* End of section. */ - line_strip_iter++; - line_strip_iter->end = true; - line_strip_iter++; - } + float value_min = waveform->data[sample_index * 3]; + float value_max = waveform->data[sample_index * 3 + 1]; + float rms = waveform->data[sample_index * 3 + 2]; + + if (sample_index + 1 < waveform->length) { + /* Use simple linear interpolation. */ + float f = sample - sample_index; + value_min = (1.0f - f) * value_min + f * waveform->data[sample_index * 3 + 3]; + value_max = (1.0f - f) * value_max + f * waveform->data[sample_index * 3 + 4]; + rms = (1.0f - f) * rms + f * waveform->data[sample_index * 3 + 5]; + if (samples_per_pixel > 1.0f) { + /* We need to sum up the values we skip over until the next step. */ + float next_pos = sample + samples_per_pixel; + int end_idx = next_pos; + + for (int j = sample_index + 1; (j < waveform->length) && (j < end_idx); j++) { + value_min = min_ff(value_min, waveform->data[j * 3]); + value_max = max_ff(value_max, waveform->data[j * 3 + 1]); + rms = max_ff(rms, waveform->data[j * 3 + 2]); } } + } - was_line_strip = is_line_strip; - - if (is_line_strip) { - line_strip_iter->pos[0] = x1_offset + i * frames_per_pixel; - line_strip_iter->pos[1] = y_mid + value_min * y_scale; - line_strip_iter->clip = clipping; - line_strip_iter++; - } - else { - tri_strip_iter->pos[0] = x1_offset + i * frames_per_pixel; - tri_strip_iter->pos[1] = y_mid + value_min * y_scale; - tri_strip_iter->clip = clipping; - tri_strip_iter->rms_pos = y_mid + max_ff(-rms, value_min) * y_scale; - tri_strip_iter++; - - tri_strip_iter->pos[0] = x1_offset + i * frames_per_pixel; - tri_strip_iter->pos[1] = y_mid + value_max * y_scale; - tri_strip_iter->clip = clipping; - tri_strip_iter->rms_pos = y_mid + min_ff(rms, value_max) * y_scale; - tri_strip_iter++; - } + float volume = seq->volume; + if (fcu && !BKE_fcurve_is_empty(fcu)) { + float evaltime = frame_start + (i * frames_per_pixel); + volume = evaluate_fcurve(fcu, evaltime); + CLAMP_MIN(volume, 0.0f); } - WaveVizData *tri_strip_end = tri_strip_iter; - WaveVizData *line_strip_end = line_strip_iter; + value_min *= volume; + value_max *= volume; + rms *= volume; - tri_strip_iter = tri_strip_arr; - line_strip_iter = line_strip_arr; + bool is_clipping = false; - draw_waveform(line_strip_iter, line_strip_end, GPU_PRIM_LINE_STRIP, false); - draw_waveform(tri_strip_iter, tri_strip_end, GPU_PRIM_TRI_STRIP, false); - draw_waveform(tri_strip_iter, tri_strip_end, GPU_PRIM_TRI_STRIP, true); + if (value_max > 1 || value_min < -1) { + is_clipping = true; + + CLAMP_MAX(value_max, 1.0f); + CLAMP_MIN(value_min, -1.0f); + } + + bool is_line_strip = (value_max - value_min < 0.05f); + /* The y coordinate for the middle of the strip. */ + float y_mid = (y1 + y2) / 2.0f; + /* The length from the middle of the strip to the top/bottom. */ + float y_scale = (y2 - y1) / 2.0f; - MEM_freeN(tri_strip_arr); - MEM_freeN(line_strip_arr); + vec2f pos = {frame_start + i * frames_per_pixel, y_mid + value_min * y_scale}; + WaveVizData *new_data = &waveform_data[wave_data_len]; + wave_data_len += waveform_append_sample( + new_data, pos, value_min, value_max, y_mid, y_scale, rms, is_clipping, is_line_strip); } + + /* Terminate array, so `get_segment_length()` can know when to stop. */ + waveform_data[wave_data_len].final_sample = true; + draw_waveform(waveform_data, wave_data_len); + MEM_freeN(waveform_data); } static void drawmeta_contents(Scene *scene, @@ -613,12 +568,12 @@ static void drawmeta_contents(Scene *scene, col[3] = 196; /* Alpha, used for all meta children. */ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* Draw only immediate children (1 level depth). */ for (seq = meta_seqbase->first; seq; seq = seq->next) { - const int startdisp = SEQ_time_left_handle_frame_get(seq) + offset; - const int enddisp = SEQ_time_right_handle_frame_get(seq) + offset; + const int startdisp = SEQ_time_left_handle_frame_get(scene, seq) + offset; + const int enddisp = SEQ_time_right_handle_frame_get(scene, seq) + offset; if ((startdisp > x2 || enddisp < x1) == 0) { float y_chan = (seq->machine - chan_min) / (float)(chan_range)*draw_range; @@ -663,19 +618,20 @@ static void drawmeta_contents(Scene *scene, GPU_blend(GPU_BLEND_NONE); } -float sequence_handle_size_get_clamped(Sequence *seq, const float pixelx) +float sequence_handle_size_get_clamped(const Scene *scene, Sequence *seq, const float pixelx) { const float maxhandle = (pixelx * SEQ_HANDLE_SIZE) * U.pixelsize; /* Ensure that handle is not wider, than quarter of strip. */ - return min_ff( - maxhandle, - ((float)(SEQ_time_right_handle_frame_get(seq) - SEQ_time_left_handle_frame_get(seq)) / - 4.0f)); + return min_ff(maxhandle, + ((float)(SEQ_time_right_handle_frame_get(scene, seq) - + SEQ_time_left_handle_frame_get(scene, seq)) / + 4.0f)); } /* Draw a handle, on left or right side of strip. */ -static void draw_seq_handle(View2D *v2d, +static void draw_seq_handle(const Scene *scene, + View2D *v2d, Sequence *seq, const float handsize_clamped, const short direction, @@ -689,8 +645,8 @@ static void draw_seq_handle(View2D *v2d, uint whichsel = 0; uchar col[4]; - x1 = SEQ_time_left_handle_frame_get(seq); - x2 = SEQ_time_right_handle_frame_get(seq); + x1 = SEQ_time_left_handle_frame_get(scene, seq); + x2 = SEQ_time_right_handle_frame_get(scene, seq); y1 = seq->machine + SEQ_STRIP_OFSBOTTOM; y2 = seq->machine + SEQ_STRIP_OFSTOP; @@ -745,8 +701,8 @@ static void draw_seq_handle(View2D *v2d, numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d%d", - SEQ_time_left_handle_frame_get(seq), - SEQ_time_right_handle_frame_get(seq)); + SEQ_time_left_handle_frame_get(scene, seq), + SEQ_time_right_handle_frame_get(scene, seq)); float tot_width = BLF_width(fontid, numstr, numstr_len); if ((x2 - x1) / pixelx > 20 + tot_width) { @@ -755,13 +711,13 @@ static void draw_seq_handle(View2D *v2d, if (direction == SEQ_LEFTHANDLE) { numstr_len = BLI_snprintf_rlen( - numstr, sizeof(numstr), "%d", SEQ_time_left_handle_frame_get(seq)); + numstr, sizeof(numstr), "%d", SEQ_time_left_handle_frame_get(scene, seq)); x1 += text_margin; y1 += 0.09f; } else { numstr_len = BLI_snprintf_rlen( - numstr, sizeof(numstr), "%d", SEQ_time_right_handle_frame_get(seq) - 1); + numstr, sizeof(numstr), "%d", SEQ_time_right_handle_frame_get(scene, seq) - 1); x1 = x2 - (text_margin + pixelx * BLF_width(fontid, numstr, numstr_len)); y1 += 0.09f; } @@ -896,7 +852,8 @@ static void draw_seq_text_get_source(Sequence *seq, char *r_source, size_t sourc } } -static size_t draw_seq_text_get_overlay_string(SpaceSeq *sseq, +static size_t draw_seq_text_get_overlay_string(const Scene *scene, + SpaceSeq *sseq, Sequence *seq, char *r_overlay_string, size_t overlay_string_len) @@ -922,8 +879,8 @@ static size_t draw_seq_text_get_overlay_string(SpaceSeq *sseq, char strip_duration_text[16]; if (sseq->timeline_overlay.flag & SEQ_TIMELINE_SHOW_STRIP_DURATION) { - const int strip_duration = SEQ_time_right_handle_frame_get(seq) - - SEQ_time_left_handle_frame_get(seq); + const int strip_duration = SEQ_time_right_handle_frame_get(scene, seq) - + SEQ_time_left_handle_frame_get(scene, seq); SNPRINTF(strip_duration_text, "%d", strip_duration); if (i != 0) { text_array[i++] = text_sep; @@ -952,7 +909,7 @@ static void draw_seq_text_overlay(Scene *scene, ListBase *channels = SEQ_channels_displayed_get(ed); char overlay_string[FILE_MAX]; size_t overlay_string_len = draw_seq_text_get_overlay_string( - sseq, seq, overlay_string, sizeof(overlay_string)); + scene, sseq, seq, overlay_string, sizeof(overlay_string)); if (overlay_string_len == 0) { return; @@ -990,8 +947,8 @@ static void draw_sequence_extensions_overlay( float x1, x2, y1, y2; uchar col[4], blend_col[3]; - x1 = SEQ_time_left_handle_frame_get(seq); - x2 = SEQ_time_right_handle_frame_get(seq); + x1 = SEQ_time_left_handle_frame_get(scene, seq); + x2 = SEQ_time_right_handle_frame_get(scene, seq); y1 = seq->machine + SEQ_STRIP_OFSBOTTOM; y2 = seq->machine + SEQ_STRIP_OFSTOP; @@ -1005,28 +962,32 @@ static void draw_sequence_extensions_overlay( col[3] = SEQ_render_is_muted(channels, seq) ? MUTE_ALPHA : 200; UI_GetColorPtrShade3ubv(col, blend_col, 10); - if (seq->startofs) { + const float strip_content_start = SEQ_time_start_frame_get(seq); + const float strip_content_end = SEQ_time_start_frame_get(seq) + + SEQ_time_strip_length_get(scene, seq); + float right_handle_frame = SEQ_time_right_handle_frame_get(scene, seq); + float left_handle_frame = SEQ_time_left_handle_frame_get(scene, seq); + + if (left_handle_frame > strip_content_start) { immUniformColor4ubv(col); - immRectf(pos, (float)(seq->start), y1 - pixely, x1, y1 - SEQ_STRIP_OFSBOTTOM); + immRectf(pos, strip_content_start, y1 - pixely, x1, y1 - SEQ_STRIP_OFSBOTTOM); /* Outline. */ immUniformColor3ubv(blend_col); - imm_draw_box_wire_2d(pos, x1, y1 - pixely, (float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM); + imm_draw_box_wire_2d(pos, x1, y1 - pixely, strip_content_start, y1 - SEQ_STRIP_OFSBOTTOM); } - if (seq->endofs) { + if (right_handle_frame < strip_content_end) { immUniformColor4ubv(col); - immRectf(pos, x2, y2 + pixely, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM); + immRectf(pos, x2, y2 + pixely, strip_content_end, y2 + SEQ_STRIP_OFSBOTTOM); - /* Outline. */ - immUniformColor3ubv(blend_col); - imm_draw_box_wire_2d( - pos, x2, y2 + pixely, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM); + /* Outline. */ immUniformColor3ubv(blend_col); + imm_draw_box_wire_2d(pos, x2, y2 + pixely, strip_content_end, y2 + SEQ_STRIP_OFSBOTTOM); } GPU_blend(GPU_BLEND_NONE); } static void draw_color_strip_band( - ListBase *channels, Sequence *seq, uint pos, float text_margin_y, float y1) + const Scene *scene, ListBase *channels, Sequence *seq, uint pos, float text_margin_y, float y1) { uchar col[4]; SolidColorVars *colvars = (SolidColorVars *)seq->effectdata; @@ -1049,9 +1010,9 @@ static void draw_color_strip_band( immUniformColor4ubv(col); immRectf(pos, - SEQ_time_left_handle_frame_get(seq), + SEQ_time_left_handle_frame_get(scene, seq), y1, - SEQ_time_right_handle_frame_get(seq), + SEQ_time_right_handle_frame_get(scene, seq), text_margin_y); /* 1px line to better separate the color band. */ @@ -1059,8 +1020,8 @@ static void draw_color_strip_band( immUniformColor4ubv(col); immBegin(GPU_PRIM_LINES, 2); - immVertex2f(pos, SEQ_time_left_handle_frame_get(seq), text_margin_y); - immVertex2f(pos, SEQ_time_right_handle_frame_get(seq), text_margin_y); + immVertex2f(pos, SEQ_time_left_handle_frame_get(scene, seq), text_margin_y); + immVertex2f(pos, SEQ_time_right_handle_frame_get(scene, seq), text_margin_y); immEnd(); GPU_blend(GPU_BLEND_NONE); @@ -1112,25 +1073,31 @@ static void draw_seq_background(Scene *scene, /* Draw the main strip body. */ if (is_single_image) { - immRectf( - pos, SEQ_time_left_handle_frame_get(seq), y1, SEQ_time_right_handle_frame_get(seq), y2); + immRectf(pos, + SEQ_time_left_handle_frame_get(scene, seq), + y1, + SEQ_time_right_handle_frame_get(scene, seq), + y2); } else { immRectf(pos, x1, y1, x2, y2); } /* Draw background for hold still regions. */ - if (!is_single_image && SEQ_time_has_still_frames(seq)) { + if (!is_single_image) { UI_GetColorPtrShade3ubv(col, col, -35); immUniformColor4ubv(col); - if (SEQ_time_has_left_still_frames(seq)) { - const float content_start = min_ff(SEQ_time_right_handle_frame_get(seq), seq->start); - immRectf(pos, SEQ_time_left_handle_frame_get(seq), y1, content_start, y2); + if (SEQ_time_has_left_still_frames(scene, seq)) { + float left_handle_frame = SEQ_time_left_handle_frame_get(scene, seq); + const float content_start = SEQ_time_start_frame_get(seq); + immRectf(pos, left_handle_frame, y1, content_start, y2); } - if (SEQ_time_has_right_still_frames(seq)) { - const float content_end = max_ff(SEQ_time_left_handle_frame_get(seq), seq->start + seq->len); - immRectf(pos, content_end, y1, SEQ_time_right_handle_frame_get(seq), y2); + if (SEQ_time_has_right_still_frames(scene, seq)) { + float right_handle_frame = SEQ_time_right_handle_frame_get(scene, seq); + const float content_end = SEQ_time_start_frame_get(seq) + + SEQ_time_strip_length_get(scene, seq); + immRectf(pos, content_end, y1, right_handle_frame, y2); } } @@ -1191,7 +1158,7 @@ static void draw_seq_invalid(float x1, float x2, float y2, float text_margin_y) GPU_blend(GPU_BLEND_ALPHA); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4f(1.0f, 0.0f, 0.0f, 0.9f); immRectf(pos, x1, y2, x2, text_margin_y); @@ -1200,9 +1167,9 @@ static void draw_seq_invalid(float x1, float x2, float y2, float text_margin_y) } static void calculate_seq_text_offsets( - View2D *v2d, Sequence *seq, float *x1, float *x2, float pixelx) + const Scene *scene, View2D *v2d, Sequence *seq, float *x1, float *x2, float pixelx) { - const float handsize_clamped = sequence_handle_size_get_clamped(seq, pixelx); + const float handsize_clamped = sequence_handle_size_get_clamped(scene, seq, pixelx); float text_margin = 2.0f * handsize_clamped; *x1 += text_margin; @@ -1309,7 +1276,7 @@ static void draw_seq_fcurve_overlay( GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO); GPU_vertbuf_data_len_set(vbo, vert_count); - GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR); + GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); GPU_batch_uniform_4f(batch, "color", 0.0f, 0.0f, 0.0f, 0.15f); GPU_blend(GPU_BLEND_ALPHA); @@ -1336,7 +1303,7 @@ static void draw_seq_strip(const bContext *C, View2D *v2d = ®ion->v2d; float x1, x2, y1, y2; - const float handsize_clamped = sequence_handle_size_get_clamped(seq, pixelx); + const float handsize_clamped = sequence_handle_size_get_clamped(scene, seq, pixelx); float pixely = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask); /* Check if we are doing "solo preview". */ @@ -1347,15 +1314,17 @@ static void draw_seq_strip(const bContext *C, SEQ_TIMELINE_SHOW_STRIP_COLOR_TAG); /* Draw strip body. */ - x1 = SEQ_time_has_left_still_frames(seq) ? seq->start : SEQ_time_left_handle_frame_get(seq); + x1 = SEQ_time_has_left_still_frames(scene, seq) ? SEQ_time_start_frame_get(seq) : + SEQ_time_left_handle_frame_get(scene, seq); y1 = seq->machine + SEQ_STRIP_OFSBOTTOM; - x2 = SEQ_time_has_right_still_frames(seq) ? (seq->start + seq->len) : - SEQ_time_right_handle_frame_get(seq); + x2 = SEQ_time_has_right_still_frames(scene, seq) ? + SEQ_time_start_frame_get(seq) + SEQ_time_strip_length_get(scene, seq) : + SEQ_time_right_handle_frame_get(scene, seq); y2 = seq->machine + SEQ_STRIP_OFSTOP; /* Limit body to strip bounds. Meta strip can end up with content outside of strip range. */ - x1 = min_ff(x1, SEQ_time_right_handle_frame_get(seq)); - x2 = max_ff(x2, SEQ_time_left_handle_frame_get(seq)); + x1 = min_ff(x1, SEQ_time_right_handle_frame_get(scene, seq)); + x2 = max_ff(x2, SEQ_time_left_handle_frame_get(scene, seq)); float text_margin_y; bool y_threshold; @@ -1375,18 +1344,18 @@ static void draw_seq_strip(const bContext *C, } uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); draw_seq_background(scene, seq, pos, x1, x2, y1, y2, is_single_image, show_strip_color_tag); /* Draw a color band inside color strip. */ if (seq->type == SEQ_TYPE_COLOR && y_threshold) { - draw_color_strip_band(channels, seq, pos, text_margin_y, y1); + draw_color_strip_band(scene, channels, seq, pos, text_margin_y, y1); } /* Draw strip offsets when flag is enabled or during "solo preview". */ if (sseq->flag & SEQ_SHOW_OVERLAY) { - if (!is_single_image && (seq->startofs || seq->endofs) && pixely > 0) { + if (!is_single_image && pixely > 0) { if ((sseq->timeline_overlay.flag & SEQ_TIMELINE_SHOW_STRIP_OFFSETS) || (seq == special_seq_update)) { draw_sequence_extensions_overlay(scene, seq, pos, pixely, show_strip_color_tag); @@ -1395,8 +1364,8 @@ static void draw_seq_strip(const bContext *C, } immUnbindProgram(); - x1 = SEQ_time_left_handle_frame_get(seq); - x2 = SEQ_time_right_handle_frame_get(seq); + x1 = SEQ_time_left_handle_frame_get(scene, seq); + x2 = SEQ_time_right_handle_frame_get(scene, seq); if ((seq->type == SEQ_TYPE_META) || ((seq->type == SEQ_TYPE_SCENE) && (seq->flag & SEQ_SCENE_STRIPS))) { @@ -1416,18 +1385,9 @@ static void draw_seq_strip(const bContext *C, } /* Draw sound strip waveform. */ - if ((seq->type == SEQ_TYPE_SOUND_RAM) && ((sseq->flag & SEQ_SHOW_OVERLAY)) && - (sseq->timeline_overlay.flag & SEQ_TIMELINE_NO_WAVEFORMS) == 0) { - draw_seq_waveform_overlay(v2d, - C, - sseq, - scene, - seq, - x1, - y_threshold ? y1 + 0.05f : y1, - x2, - y_threshold ? text_margin_y : y2, - BLI_rctf_size_x(®ion->v2d.cur) / region->winx); + if (seq_draw_waveforms_poll(C, sseq, seq)) { + draw_seq_waveform_overlay( + C, region, seq, x1, y_threshold ? y1 + 0.05f : y1, x2, y_threshold ? text_margin_y : y2); } /* Draw locked state. */ if (SEQ_transform_is_locked(channels, seq)) { @@ -1440,20 +1400,20 @@ static void draw_seq_strip(const bContext *C, } pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); if (!SEQ_transform_is_locked(channels, seq)) { draw_seq_handle( - v2d, seq, handsize_clamped, SEQ_LEFTHANDLE, pos, seq_active, pixelx, y_threshold); + scene, v2d, seq, handsize_clamped, SEQ_LEFTHANDLE, pos, seq_active, pixelx, y_threshold); draw_seq_handle( - v2d, seq, handsize_clamped, SEQ_RIGHTHANDLE, pos, seq_active, pixelx, y_threshold); + scene, v2d, seq, handsize_clamped, SEQ_RIGHTHANDLE, pos, seq_active, pixelx, y_threshold); } draw_seq_outline(scene, seq, pos, x1, x2, y1, y2, pixelx, pixely, seq_active); immUnbindProgram(); - calculate_seq_text_offsets(v2d, seq, &x1, &x2, pixelx); + calculate_seq_text_offsets(scene, v2d, seq, &x1, &x2, pixelx); /* If a waveform is drawn, avoid drawing text when there is not enough vertical space. */ if (seq->type == SEQ_TYPE_SOUND_RAM) { @@ -1474,7 +1434,7 @@ static void draw_seq_strip(const bContext *C, } } -static void draw_effect_inputs_highlight(Sequence *seq) +static void draw_effect_inputs_highlight(const Scene *scene, Sequence *seq) { Sequence *seq1 = seq->seq1; Sequence *seq2 = seq->seq2; @@ -1482,27 +1442,27 @@ static void draw_effect_inputs_highlight(Sequence *seq) GPU_blend(GPU_BLEND_ALPHA); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4ub(255, 255, 255, 48); immRectf(pos, - SEQ_time_left_handle_frame_get(seq1), + SEQ_time_left_handle_frame_get(scene, seq1), seq1->machine + SEQ_STRIP_OFSBOTTOM, - SEQ_time_right_handle_frame_get(seq1), + SEQ_time_right_handle_frame_get(scene, seq1), seq1->machine + SEQ_STRIP_OFSTOP); if (seq2 && seq2 != seq1) { immRectf(pos, - SEQ_time_left_handle_frame_get(seq2), + SEQ_time_left_handle_frame_get(scene, seq2), seq2->machine + SEQ_STRIP_OFSBOTTOM, - SEQ_time_right_handle_frame_get(seq2), + SEQ_time_right_handle_frame_get(scene, seq2), seq2->machine + SEQ_STRIP_OFSTOP); } if (seq3 && !ELEM(seq3, seq1, seq2)) { immRectf(pos, - SEQ_time_left_handle_frame_get(seq3), + SEQ_time_left_handle_frame_get(scene, seq3), seq3->machine + SEQ_STRIP_OFSBOTTOM, - SEQ_time_right_handle_frame_get(seq3), + SEQ_time_right_handle_frame_get(scene, seq3), seq3->machine + SEQ_STRIP_OFSTOP); } immUnbindProgram(); @@ -1591,7 +1551,8 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, } if (viewport) { - /* Follows same logic as wm_draw_window_offscreen to make sure to restore the same viewport. */ + /* Follows same logic as wm_draw_window_offscreen to make sure to restore the same + * viewport. */ int view = (sseq->multiview_eye == STEREO_RIGHT_ID) ? 1 : 0; GPU_viewport_bind(viewport, view, ®ion->winrct); } @@ -1688,7 +1649,7 @@ static void sequencer_draw_borders_overlay(const SpaceSeq *sseq, const uint shdr_pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -1747,8 +1708,7 @@ void sequencer_draw_maskedit(const bContext *C, Scene *scene, ARegion *region, S // ED_mask_get_size(C, &width, &height); //Scene *scene = CTX_data_scene(C); - width = (scene->r.size * scene->r.xsch) / 100; - height = (scene->r.size * scene->r.ysch) / 100; + BKE_render_resolution(&scene->r, false, &width, &height); ED_mask_draw_region(mask, region, @@ -1960,7 +1920,7 @@ static void sequencer_draw_display_buffer(const bContext *C, GPU_texture_bind(texture, 0); if (!glsl_used) { - immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_COLOR); immUniformColor3f(1.0f, 1.0f, 1.0f); } @@ -2096,10 +2056,10 @@ static int sequencer_draw_get_transform_preview_frame(Scene *scene) int preview_frame; if (last_seq->flag & SEQ_RIGHTSEL) { - preview_frame = SEQ_time_right_handle_frame_get(last_seq) - 1; + preview_frame = SEQ_time_right_handle_frame_get(scene, last_seq) - 1; } else { - preview_frame = SEQ_time_left_handle_frame_get(last_seq); + preview_frame = SEQ_time_left_handle_frame_get(scene, last_seq); } return preview_frame; @@ -2149,7 +2109,7 @@ static void seq_draw_image_origin_and_outline(const bContext *C, Sequence *seq, GPU_line_smooth(true); GPU_blend(GPU_BLEND_ALPHA); GPU_line_width(2); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); float col[3]; if (is_active_seq) { @@ -2253,7 +2213,7 @@ void sequencer_draw_preview(const bContext *C, Editing *ed = SEQ_editing_get(scene); ListBase *channels = SEQ_channels_displayed_get(ed); SeqCollection *collection = SEQ_query_rendered_strips( - channels, ed->seqbasep, timeline_frame, 0); + scene, channels, ed->seqbasep, timeline_frame, 0); Sequence *seq; Sequence *active_seq = SEQ_select_active_get(scene); SEQ_ITERATOR_FOREACH (seq, collection) { @@ -2287,7 +2247,7 @@ void sequencer_draw_preview(const bContext *C, static void draw_seq_timeline_channels(View2D *v2d) { uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_blend(GPU_BLEND_ALPHA); immUniformThemeColor(TH_ROW_ALTERNATE); @@ -2325,10 +2285,13 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *region) if (seq == last_seq && (last_seq->flag & SELECT)) { continue; } - if (min_ii(SEQ_time_left_handle_frame_get(seq), seq->start) > v2d->cur.xmax) { + if (min_ii(SEQ_time_left_handle_frame_get(scene, seq), SEQ_time_start_frame_get(seq)) > + v2d->cur.xmax) { continue; } - if (max_ii(SEQ_time_right_handle_frame_get(seq), seq->start + seq->len) < v2d->cur.xmin) { + if (max_ii(SEQ_time_right_handle_frame_get(scene, seq), + SEQ_time_start_frame_get(seq) + SEQ_time_strip_length_get(scene, seq)) < + v2d->cur.xmin) { continue; } if (seq->machine + 1.0f < v2d->cur.ymin) { @@ -2353,7 +2316,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *region) /* When active strip is an effect, highlight its inputs. */ if (SEQ_effect_get_num_inputs(last_seq->type) > 0) { - draw_effect_inputs_highlight(last_seq); + draw_effect_inputs_highlight(scene, last_seq); } /* When active is a Multi-cam strip, highlight its source channel. */ else if (last_seq->type == SEQ_TYPE_MULTICAM) { @@ -2362,7 +2325,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *region) GPU_blend(GPU_BLEND_ALPHA); uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4ub(255, 255, 255, 48); immRectf(pos, v2d->cur.xmin, channel, v2d->cur.xmax, channel + 1); @@ -2379,13 +2342,13 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *region) GPU_blend(GPU_BLEND_ALPHA); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4ub(255, 255, 255, 48); immRectf(pos, - SEQ_time_left_handle_frame_get(seq), + SEQ_time_left_handle_frame_get(scene, seq), seq->machine + SEQ_STRIP_OFSBOTTOM, - SEQ_time_right_handle_frame_get(seq), + SEQ_time_right_handle_frame_get(scene, seq), seq->machine + SEQ_STRIP_OFSTOP); immUnbindProgram(); @@ -2403,7 +2366,7 @@ static void seq_draw_sfra_efra(const Scene *scene, View2D *v2d) GPU_blend(GPU_BLEND_ALPHA); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* Draw overlay outside of frame range. */ immUniformThemeColorShadeAlpha(TH_BACK, -10, -100); @@ -2445,7 +2408,7 @@ static void seq_draw_sfra_efra(const Scene *scene, View2D *v2d) immUnbindProgram(); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformThemeColorShade(TH_BACK, -40); immBegin(GPU_PRIM_LINES, 4); @@ -2569,7 +2532,7 @@ static void draw_cache_view_batch( GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO); if (vert_count > 0) { GPU_vertbuf_data_len_set(vbo, vert_count); - GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR); + GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); GPU_batch_uniform_4f(batch, "color", col_r, col_g, col_b, col_a); GPU_batch_draw(batch); } @@ -2588,7 +2551,7 @@ static void draw_cache_view(const bContext *C) GPU_blend(GPU_BLEND_ALPHA); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); float stripe_bot, stripe_top; float stripe_ofs_y = UI_view2d_region_to_view_y(v2d, 1.0f) - v2d->cur.ymin; @@ -2612,8 +2575,8 @@ static void draw_cache_view(const bContext *C) continue; } - if (SEQ_time_left_handle_frame_get(seq) > v2d->cur.xmax || - SEQ_time_right_handle_frame_get(seq) < v2d->cur.xmin) { + if (SEQ_time_left_handle_frame_get(scene, seq) > v2d->cur.xmax || + SEQ_time_right_handle_frame_get(scene, seq) < v2d->cur.xmin) { continue; } @@ -2624,9 +2587,9 @@ static void draw_cache_view(const bContext *C) const float bg_color[4] = {1.0f, 0.1f, 0.02f, 0.1f}; immUniformColor4f(bg_color[0], bg_color[1], bg_color[2], bg_color[3]); immRectf(pos, - SEQ_time_left_handle_frame_get(seq), + SEQ_time_left_handle_frame_get(scene, seq), stripe_bot, - SEQ_time_right_handle_frame_get(seq), + SEQ_time_right_handle_frame_get(scene, seq), stripe_top); } @@ -2637,9 +2600,9 @@ static void draw_cache_view(const bContext *C) const float bg_color[4] = {0.1f, 0.1f, 0.75f, 0.1f}; immUniformColor4f(bg_color[0], bg_color[1], bg_color[2], bg_color[3]); immRectf(pos, - SEQ_time_left_handle_frame_get(seq), + SEQ_time_left_handle_frame_get(scene, seq), stripe_bot, - SEQ_time_right_handle_frame_get(seq), + SEQ_time_right_handle_frame_get(scene, seq), stripe_top); } @@ -2650,9 +2613,9 @@ static void draw_cache_view(const bContext *C) const float bg_color[4] = {1.0f, 0.6f, 0.0f, 0.1f}; immUniformColor4f(bg_color[0], bg_color[1], bg_color[2], bg_color[3]); immRectf(pos, - SEQ_time_left_handle_frame_get(seq), + SEQ_time_left_handle_frame_get(scene, seq), stripe_bot, - SEQ_time_right_handle_frame_get(seq), + SEQ_time_right_handle_frame_get(scene, seq), stripe_top); } } @@ -2697,7 +2660,7 @@ static void draw_overlap_frame_indicator(const struct Scene *scene, const View2D scene->r.cfra + scene->ed->overlay_frame_ofs; uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 86c438c616e..415bb5898a9 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -54,6 +54,7 @@ #include "RNA_prototypes.h" /* For menu, popup, icons, etc. */ +#include "ED_fileselect.h" #include "ED_keyframing.h" #include "ED_numinput.h" #include "ED_outliner.h" @@ -81,6 +82,7 @@ typedef struct TransSeq { int anim_startofs, anim_endofs; /* int final_left, final_right; */ /* UNUSED */ int len; + float content_start; } TransSeq; /** \} */ @@ -173,6 +175,11 @@ bool sequencer_edit_poll(bContext *C) return (SEQ_editing_get(CTX_data_scene(C)) != NULL); } +bool sequencer_editing_initialized_and_active(bContext *C) +{ + return ED_operator_sequencer_active(C) && sequencer_edit_poll(C); +} + #if 0 /* UNUSED */ bool sequencer_strip_poll(bContext *C) { @@ -259,7 +266,7 @@ static int sequencer_gap_remove_exec(bContext *C, wmOperator *op) const bool do_all = RNA_boolean_get(op->ptr, "all"); const Editing *ed = SEQ_editing_get(scene); - SEQ_edit_remove_gaps(scene, ed->seqbasep, CFRA, do_all); + SEQ_edit_remove_gaps(scene, ed->seqbasep, scene->r.cfra, do_all); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); @@ -298,7 +305,7 @@ static int sequencer_gap_insert_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); const int frames = RNA_int_get(op->ptr, "frames"); const Editing *ed = SEQ_editing_get(scene); - SEQ_transform_offset_after_frame(scene, ed->seqbasep, frames, CFRA); + SEQ_transform_offset_after_frame(scene, ed->seqbasep, frames, scene->r.cfra); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -364,8 +371,6 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op) else { /* SEQ_RIGHTSEL */ SEQ_time_right_handle_frame_set(scene, seq, snap_frame); } - SEQ_transform_handle_xlimits( - scene, seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL); SEQ_transform_fix_single_image_seq_offsets(scene, seq); } } @@ -375,7 +380,7 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op) for (seq = ed->seqbasep->first; seq; seq = seq->next) { if (seq->flag & SELECT && !SEQ_transform_is_locked(channels, seq)) { seq->flag &= ~SEQ_OVERLAP; - if (SEQ_transform_test_overlap(ed->seqbasep, seq)) { + if (SEQ_transform_test_overlap(scene, ed->seqbasep, seq)) { SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene); } } @@ -388,17 +393,20 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op) if (seq->seq1 && (seq->seq1->flag & SELECT)) { if (!either_handle_selected) { - SEQ_offset_animdata(scene, seq, (snap_frame - SEQ_time_left_handle_frame_get(seq))); + SEQ_offset_animdata( + scene, seq, (snap_frame - SEQ_time_left_handle_frame_get(scene, seq))); } } else if (seq->seq2 && (seq->seq2->flag & SELECT)) { if (!either_handle_selected) { - SEQ_offset_animdata(scene, seq, (snap_frame - SEQ_time_left_handle_frame_get(seq))); + SEQ_offset_animdata( + scene, seq, (snap_frame - SEQ_time_left_handle_frame_get(scene, seq))); } } else if (seq->seq3 && (seq->seq3->flag & SELECT)) { if (!either_handle_selected) { - SEQ_offset_animdata(scene, seq, (snap_frame - SEQ_time_left_handle_frame_get(seq))); + SEQ_offset_animdata( + scene, seq, (snap_frame - SEQ_time_left_handle_frame_get(scene, seq))); } } } @@ -416,7 +424,7 @@ static int sequencer_snap_invoke(bContext *C, wmOperator *op, const wmEvent *UNU int snap_frame; - snap_frame = CFRA; + snap_frame = scene->r.cfra; RNA_int_set(op->ptr, "frame", snap_frame); return sequencer_snap_exec(C, op); @@ -468,6 +476,7 @@ typedef struct SlipData { static void transseq_backup(TransSeq *ts, Sequence *seq) { + ts->content_start = SEQ_time_start_frame_get(seq); ts->start = seq->start; ts->machine = seq->machine; ts->startofs = seq->startofs; @@ -598,7 +607,7 @@ static void sequencer_slip_recursively(Scene *scene, SlipData *data, int offset) } /* Make sure, that each strip contains at least 1 frame of content. */ -static void sequencer_slip_apply_limits(SlipData *data, int *offset) +static void sequencer_slip_apply_limits(const Scene *scene, SlipData *data, int *offset) { for (int i = 0; i < data->num_seq; i++) { if (data->trim[i]) { @@ -607,12 +616,12 @@ static void sequencer_slip_apply_limits(SlipData *data, int *offset) int seq_content_end = seq_content_start + seq->len + seq->anim_startofs + seq->anim_endofs; int diff = 0; - if (seq_content_start >= SEQ_time_right_handle_frame_get(seq)) { - diff = SEQ_time_right_handle_frame_get(seq) - seq_content_start - 1; + if (seq_content_start >= SEQ_time_right_handle_frame_get(scene, seq)) { + diff = SEQ_time_right_handle_frame_get(scene, seq) - seq_content_start - 1; } - if (seq_content_end <= SEQ_time_left_handle_frame_get(seq)) { - diff = SEQ_time_left_handle_frame_get(seq) - seq_content_end + 1; + if (seq_content_end <= SEQ_time_left_handle_frame_get(scene, seq)) { + diff = SEQ_time_left_handle_frame_get(scene, seq) - seq_content_end + 1; } *offset += diff; } @@ -644,7 +653,7 @@ static int sequencer_slip_exec(bContext *C, wmOperator *op) transseq_backup(data->ts + i, data->seq_array[i]); } - sequencer_slip_apply_limits(data, &offset); + sequencer_slip_apply_limits(scene, data, &offset); sequencer_slip_recursively(scene, data, offset); MEM_freeN(data->seq_array); @@ -690,7 +699,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even applyNumInput(&data->num_input, &offset_fl); int offset = round_fl_to_int(offset_fl); - sequencer_slip_apply_limits(data, &offset); + sequencer_slip_apply_limits(scene, data, &offset); sequencer_slip_update_header(scene, area, data, offset); RNA_int_set(op->ptr, "offset", offset); @@ -722,7 +731,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even UI_view2d_region_to_view(v2d, mouse_x, 0, &mouseloc[0], &mouseloc[1]); offset = mouseloc[0] - data->init_mouseloc[0]; - sequencer_slip_apply_limits(data, &offset); + sequencer_slip_apply_limits(scene, data, &offset); sequencer_slip_update_header(scene, area, data, offset); RNA_int_set(op->ptr, "offset", offset); @@ -799,7 +808,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even applyNumInput(&data->num_input, &offset_fl); int offset = round_fl_to_int(offset_fl); - sequencer_slip_apply_limits(data, &offset); + sequencer_slip_apply_limits(scene, data, &offset); sequencer_slip_update_header(scene, area, data, offset); RNA_int_set(op->ptr, "offset", offset); @@ -1047,7 +1056,7 @@ static int sequencer_reload_exec(bContext *C, wmOperator *op) SEQ_add_reload_new_file(bmain, scene, seq, !adjust_length); if (adjust_length) { - if (SEQ_transform_test_overlap(ed->seqbasep, seq)) { + if (SEQ_transform_test_overlap(scene, ed->seqbasep, seq)) { SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene); } } @@ -1410,14 +1419,14 @@ static int sequencer_split_exec(bContext *C, wmOperator *op) if (ignore_selection) { if (use_cursor_position) { LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) { - if (SEQ_time_right_handle_frame_get(seq) == split_frame && + if (SEQ_time_right_handle_frame_get(scene, seq) == split_frame && seq->machine == split_channel) { seq_selected = seq->flag & SEQ_ALLSEL; } } if (!seq_selected) { LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) { - if (SEQ_time_left_handle_frame_get(seq) == split_frame && + if (SEQ_time_left_handle_frame_get(scene, seq) == split_frame && seq->machine == split_channel) { seq->flag &= ~SEQ_ALLSEL; } @@ -1429,12 +1438,12 @@ static int sequencer_split_exec(bContext *C, wmOperator *op) if (split_side != SEQ_SIDE_BOTH) { LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) { if (split_side == SEQ_SIDE_LEFT) { - if (SEQ_time_left_handle_frame_get(seq) >= split_frame) { + if (SEQ_time_left_handle_frame_get(scene, seq) >= split_frame) { seq->flag &= ~SEQ_ALLSEL; } } else { - if (SEQ_time_right_handle_frame_get(seq) <= split_frame) { + if (SEQ_time_right_handle_frame_get(scene, seq) <= split_frame) { seq->flag &= ~SEQ_ALLSEL; } } @@ -1457,7 +1466,7 @@ static int sequencer_split_invoke(bContext *C, wmOperator *op, const wmEvent *ev View2D *v2d = UI_view2d_fromcontext(C); int split_side = RNA_enum_get(op->ptr, "side"); - int split_frame = CFRA; + int split_frame = scene->r.cfra; if (split_side == SEQ_SIDE_MOUSE) { if (ED_operator_sequencer_active(C) && v2d) { @@ -1695,8 +1704,10 @@ static int sequencer_delete_exec(bContext *C, wmOperator *op) static int sequencer_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *region = CTX_wm_region(C); + Scene *scene = CTX_data_scene(C); + ListBase *markers = &scene->markers; - if (region->regiontype == RGN_TYPE_WINDOW) { + if (region->regiontype == RGN_TYPE_WINDOW && !BLI_listbase_is_empty(markers)) { /* Bounding box of 30 pixels is used for markers shortcuts, * prevent conflict with markers shortcuts here. */ @@ -1761,7 +1772,7 @@ static int sequencer_offset_clear_exec(bContext *C, wmOperator *UNUSED(op)) for (seq = ed->seqbasep->first; seq; seq = seq->next) { if ((seq->type & SEQ_TYPE_EFFECT) == 0 && (seq->flag & SELECT)) { - if (SEQ_transform_test_overlap(ed->seqbasep, seq)) { + if (SEQ_transform_test_overlap(scene, ed->seqbasep, seq)) { SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene); } } @@ -1820,12 +1831,12 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op) /* TODO: remove f-curve and assign to split image strips. * The old animation system would remove the user of `seq->ipo`. */ - start_ofs = timeline_frame = SEQ_time_left_handle_frame_get(seq); - frame_end = SEQ_time_right_handle_frame_get(seq); + start_ofs = timeline_frame = SEQ_time_left_handle_frame_get(scene, seq); + frame_end = SEQ_time_right_handle_frame_get(scene, seq); while (timeline_frame < frame_end) { /* New seq. */ - se = SEQ_render_give_stripelem(seq, timeline_frame); + se = SEQ_render_give_stripelem(scene, seq, timeline_frame); seq_new = SEQ_sequence_dupli_recursive(scene, scene, seqbase, seq, SEQ_DUPE_UNIQUE_NAME); @@ -1847,7 +1858,7 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op) if (step > 1) { seq_new->flag &= ~SEQ_OVERLAP; - if (SEQ_transform_test_overlap(seqbase, seq_new)) { + if (SEQ_transform_test_overlap(scene, seqbase, seq_new)) { SEQ_transform_seqbase_shuffle(seqbase, seq_new, scene); } } @@ -1906,11 +1917,9 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op)) SEQ_prefetch_stop(scene); if (active_seq && active_seq->type == SEQ_TYPE_META && active_seq->flag & SELECT) { - /* Enter meta-strip. */ - SEQ_meta_stack_alloc(ed, active_seq); - SEQ_seqbase_active_set(ed, &active_seq->seqbase); - SEQ_channels_displayed_set(ed, &active_seq->channels); + /* Deselect active meta seq. */ SEQ_select_active_set(scene, NULL); + SEQ_meta_stack_set(scene, active_seq); } else { /* Exit meta-strip if possible. */ @@ -1918,11 +1927,9 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } - MetaStack *ms = SEQ_meta_stack_active_get(ed); - SEQ_seqbase_active_set(ed, ms->oldbasep); - SEQ_channels_displayed_set(ed, ms->old_channels); - SEQ_select_active_set(scene, ms->parseq); - SEQ_meta_stack_free(ed, ms); + /* Display parent meta. */ + Sequence *meta_parent = SEQ_meta_stack_pop(ed); + SEQ_select_active_set(scene, meta_parent); } DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); @@ -1977,8 +1984,8 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op) BLI_addtail(&seqm->seqbase, seq); SEQ_relations_invalidate_cache_preprocessed(scene, seq); channel_max = max_ii(seq->machine, channel_max); - meta_start_frame = min_ii(SEQ_time_left_handle_frame_get(seq), meta_start_frame); - meta_end_frame = max_ii(SEQ_time_right_handle_frame_get(seq), meta_end_frame); + meta_start_frame = min_ii(SEQ_time_left_handle_frame_get(scene, seq), meta_start_frame); + meta_end_frame = max_ii(SEQ_time_right_handle_frame_get(scene, seq), meta_end_frame); } } @@ -1988,7 +1995,7 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op) seqm->start = meta_start_frame; seqm->len = meta_end_frame - meta_start_frame; SEQ_select_active_set(scene, seqm); - if (SEQ_transform_test_overlap(active_seqbase, seqm)) { + if (SEQ_transform_test_overlap(scene, active_seqbase, seqm)) { SEQ_transform_seqbase_shuffle(active_seqbase, seqm, scene); } @@ -2048,7 +2055,7 @@ static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op)) LISTBASE_FOREACH (Sequence *, seq, active_seqbase) { if (seq->flag & SELECT) { seq->flag &= ~SEQ_OVERLAP; - if (SEQ_transform_test_overlap(active_seqbase, seq)) { + if (SEQ_transform_test_overlap(scene, active_seqbase, seq)) { SEQ_transform_seqbase_shuffle(active_seqbase, seq, scene); } } @@ -2087,12 +2094,12 @@ static bool strip_jump_internal(Scene *scene, const bool do_center) { bool changed = false; - int timeline_frame = CFRA; + int timeline_frame = scene->r.cfra; int next_frame = SEQ_time_find_next_prev_edit( scene, timeline_frame, side, do_skip_mute, do_center, false); if (next_frame != timeline_frame) { - CFRA = next_frame; + scene->r.cfra = next_frame; changed = true; } @@ -2159,17 +2166,18 @@ static const EnumPropertyItem prop_side_lr_types[] = { static void swap_sequence(Scene *scene, Sequence *seqa, Sequence *seqb) { - int gap = SEQ_time_left_handle_frame_get(seqb) - SEQ_time_right_handle_frame_get(seqa); + int gap = SEQ_time_left_handle_frame_get(scene, seqb) - + SEQ_time_right_handle_frame_get(scene, seqa); int seq_a_start; int seq_b_start; - seq_b_start = (seqb->start - SEQ_time_left_handle_frame_get(seqb)) + - SEQ_time_left_handle_frame_get(seqa); + seq_b_start = (seqb->start - SEQ_time_left_handle_frame_get(scene, seqb)) + + SEQ_time_left_handle_frame_get(scene, seqa); SEQ_transform_translate_sequence(scene, seqb, seq_b_start - seqb->start); SEQ_relations_invalidate_cache_preprocessed(scene, seqb); - seq_a_start = (seqa->start - SEQ_time_left_handle_frame_get(seqa)) + - SEQ_time_right_handle_frame_get(seqb) + gap; + seq_a_start = (seqa->start - SEQ_time_left_handle_frame_get(scene, seqa)) + + SEQ_time_right_handle_frame_get(scene, seqb) + gap; SEQ_transform_translate_sequence(scene, seqa, seq_a_start - seqa->start); SEQ_relations_invalidate_cache_preprocessed(scene, seqa); } @@ -2195,13 +2203,17 @@ static Sequence *find_next_prev_sequence(Scene *scene, Sequence *test, int lr, i switch (lr) { case SEQ_SIDE_LEFT: - if (SEQ_time_right_handle_frame_get(seq) <= SEQ_time_left_handle_frame_get(test)) { - dist = SEQ_time_right_handle_frame_get(test) - SEQ_time_left_handle_frame_get(seq); + if (SEQ_time_right_handle_frame_get(scene, seq) <= + SEQ_time_left_handle_frame_get(scene, test)) { + dist = SEQ_time_right_handle_frame_get(scene, test) - + SEQ_time_left_handle_frame_get(scene, seq); } break; case SEQ_SIDE_RIGHT: - if (SEQ_time_left_handle_frame_get(seq) >= SEQ_time_right_handle_frame_get(test)) { - dist = SEQ_time_left_handle_frame_get(seq) - SEQ_time_right_handle_frame_get(test); + if (SEQ_time_left_handle_frame_get(scene, seq) >= + SEQ_time_right_handle_frame_get(scene, test)) { + dist = SEQ_time_left_handle_frame_get(scene, seq) - + SEQ_time_right_handle_frame_get(scene, test); } break; } @@ -2266,7 +2278,7 @@ static int sequencer_swap_exec(bContext *C, wmOperator *op) if ((iseq->type & SEQ_TYPE_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) { /* This may now overlap. */ - if (SEQ_transform_test_overlap(seqbase, iseq)) { + if (SEQ_transform_test_overlap(scene, seqbase, iseq)) { SEQ_transform_seqbase_shuffle(seqbase, iseq, scene); } } @@ -2316,7 +2328,7 @@ static int sequencer_rendersize_exec(bContext *C, wmOperator *UNUSED(op)) switch (active_seq->type) { case SEQ_TYPE_IMAGE: - se = SEQ_render_give_stripelem(active_seq, scene->r.cfra); + se = SEQ_render_give_stripelem(scene, active_seq, scene->r.cfra); break; case SEQ_TYPE_MOVIE: se = active_seq->strip->stripdata; @@ -2527,8 +2539,8 @@ static int sequencer_paste_exec(bContext *C, wmOperator *op) else { int min_seq_startdisp = INT_MAX; LISTBASE_FOREACH (Sequence *, seq, &seqbase_clipboard) { - if (SEQ_time_left_handle_frame_get(seq) < min_seq_startdisp) { - min_seq_startdisp = SEQ_time_left_handle_frame_get(seq); + if (SEQ_time_left_handle_frame_get(scene, seq) < min_seq_startdisp) { + min_seq_startdisp = SEQ_time_left_handle_frame_get(scene, seq); } } /* Paste strips relative to the current-frame. */ @@ -2574,7 +2586,7 @@ static int sequencer_paste_exec(bContext *C, wmOperator *op) * strip. */ SEQ_transform_translate_sequence(scene, iseq, ofs); /* Ensure, that pasted strips don't overlap. */ - if (SEQ_transform_test_overlap(ed->seqbasep, iseq)) { + if (SEQ_transform_test_overlap(scene, ed->seqbasep, iseq)) { SEQ_transform_seqbase_shuffle(ed->seqbasep, iseq, scene); } } @@ -2626,12 +2638,12 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op) Sequence *seq_other; const char *error_msg; - if (SEQ_select_active_get_pair(scene, &seq_act, &seq_other) == 0) { + if (SEQ_select_active_get_pair(scene, &seq_act, &seq_other) == false) { BKE_report(op->reports, RPT_ERROR, "Please select two strips"); return OPERATOR_CANCELLED; } - if (SEQ_edit_sequence_swap(seq_act, seq_other, &error_msg) == 0) { + if (SEQ_edit_sequence_swap(scene, seq_act, seq_other, &error_msg) == false) { BKE_report(op->reports, RPT_ERROR, error_msg); return OPERATOR_CANCELLED; } @@ -2858,7 +2870,7 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op) RNA_string_get(op->ptr, "directory", directory); if (is_relative_path) { - /* TODO(campbell): shouldn't this already be relative from the filesel? + /* TODO(@campbellbarton): shouldn't this already be relative from the filesel? * (as the 'filepath' is) for now just make relative here, * but look into changing after 2.60. */ BLI_path_rel(directory, BKE_main_blendfile_path(bmain)); @@ -3056,13 +3068,14 @@ void SEQUENCER_OT_change_scene(struct wmOperatorType *ot) * \{ */ /** Comparison function suitable to be used with BLI_listbase_sort(). */ -static int seq_cmp_time_startdisp_channel(const void *a, const void *b) +static int seq_cmp_time_startdisp_channel(void *thunk, const void *a, const void *b) { + const Scene *scene = thunk; Sequence *seq_a = (Sequence *)a; Sequence *seq_b = (Sequence *)b; - int seq_a_start = SEQ_time_left_handle_frame_get(seq_a); - int seq_b_start = SEQ_time_left_handle_frame_get(seq_b); + int seq_a_start = SEQ_time_left_handle_frame_get(scene, seq_a); + int seq_b_start = SEQ_time_left_handle_frame_get(scene, seq_b); /* If strips have the same start frame favor the one with a higher channel. */ if (seq_a_start == seq_b_start) { @@ -3076,20 +3089,7 @@ static int sequencer_export_subtitles_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - Main *bmain = CTX_data_main(C); - if (!RNA_struct_property_is_set(op->ptr, "filepath")) { - char filepath[FILE_MAX]; - - if (BKE_main_blendfile_path(bmain)[0] == '\0') { - BLI_strncpy(filepath, "untitled", sizeof(filepath)); - } - else { - BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath)); - } - - BLI_path_extension_replace(filepath, sizeof(filepath), ".srt"); - RNA_string_set(op->ptr, "filepath", filepath); - } + ED_fileselect_ensure_default_filepath(C, op, ".srt"); WM_event_add_fileselect(C, op); @@ -3108,7 +3108,7 @@ static bool seq_get_text_strip_cb(Sequence *seq, void *user_data) ListBase *channels = SEQ_channels_displayed_get(ed); /* Only text strips that are not muted and don't end with negative frame. */ if ((seq->type == SEQ_TYPE_TEXT) && !SEQ_render_is_muted(channels, seq) && - (SEQ_time_right_handle_frame_get(seq) > cd->scene->r.sfra)) { + (SEQ_time_right_handle_frame_get(cd->scene, seq) > cd->scene->r.sfra)) { BLI_addtail(cd->text_seq, MEM_dupallocN(seq)); } return true; @@ -3124,7 +3124,7 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op) FILE *file; char filepath[FILE_MAX]; - if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) { BKE_report(op->reports, RPT_ERROR, "No filename given"); return OPERATOR_CANCELLED; } @@ -3155,7 +3155,7 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BLI_listbase_sort(&text_seq, seq_cmp_time_startdisp_channel); + BLI_listbase_sort_r(&text_seq, seq_cmp_time_startdisp_channel, scene); /* Open and write file. */ file = BLI_fopen(filepath, "w"); @@ -3170,15 +3170,16 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op) timecode_str_start, sizeof(timecode_str_start), -2, - FRA2TIME(max_ii(SEQ_time_left_handle_frame_get(seq) - scene->r.sfra, 0)), + FRA2TIME(max_ii(SEQ_time_left_handle_frame_get(scene, seq) - scene->r.sfra, 0)), + FPS, + USER_TIMECODE_SUBRIP); + BLI_timecode_string_from_time( + timecode_str_end, + sizeof(timecode_str_end), + -2, + FRA2TIME(SEQ_time_right_handle_frame_get(scene, seq) - scene->r.sfra), FPS, USER_TIMECODE_SUBRIP); - BLI_timecode_string_from_time(timecode_str_end, - sizeof(timecode_str_end), - -2, - FRA2TIME(SEQ_time_right_handle_frame_get(seq) - scene->r.sfra), - FPS, - USER_TIMECODE_SUBRIP); fprintf( file, "%d\n%s --> %s\n%s\n\n", iter++, timecode_str_start, timecode_str_end, data->text); @@ -3244,8 +3245,8 @@ static int sequencer_set_range_to_strips_exec(bContext *C, wmOperator *op) for (seq = ed->seqbasep->first; seq; seq = seq->next) { if (seq->flag & SELECT) { selected = true; - sfra = min_ii(sfra, SEQ_time_left_handle_frame_get(seq)); - efra = max_ii(efra, SEQ_time_right_handle_frame_get(seq) - 1); + sfra = min_ii(sfra, SEQ_time_left_handle_frame_get(scene, seq)); + efra = max_ii(efra, SEQ_time_right_handle_frame_get(scene, seq) - 1); } } @@ -3397,8 +3398,8 @@ static int sequencer_strip_transform_fit_exec(bContext *C, wmOperator *op) for (seq = ed->seqbasep->first; seq; seq = seq->next) { if (seq->flag & SELECT && seq->type != SEQ_TYPE_SOUND_RAM) { - const int timeline_frame = CFRA; - StripElem *strip_elem = SEQ_render_give_stripelem(seq, timeline_frame); + const int timeline_frame = scene->r.cfra; + StripElem *strip_elem = SEQ_render_give_stripelem(scene, seq, timeline_frame); if (strip_elem == NULL) { continue; diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h index 3307c3fde2f..644e897f631 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.h +++ b/source/blender/editors/space_sequencer/sequencer_intern.h @@ -70,7 +70,9 @@ void color3ubv_from_seq(const struct Scene *curscene, void sequencer_special_update_set(Sequence *seq); /* Get handle width in 2d-View space. */ -float sequence_handle_size_get_clamped(struct Sequence *seq, float pixelx); +float sequence_handle_size_get_clamped(const struct Scene *scene, + struct Sequence *seq, + float pixelx); /* UNUSED */ /* void seq_reset_imageofs(struct SpaceSeq *sseq); */ @@ -113,7 +115,7 @@ void channel_draw_context_init(const struct bContext *C, /* sequencer_edit.c */ struct View2D; -void seq_rectf(struct Sequence *seq, struct rctf *rectf); +void seq_rectf(const struct Scene *scene, struct Sequence *seq, struct rctf *rectf); struct Sequence *find_nearest_seq(struct Scene *scene, struct View2D *v2d, int *hand, @@ -133,6 +135,7 @@ int seq_effect_find_selected(struct Scene *scene, /* Operator helpers. */ bool sequencer_edit_poll(struct bContext *C); +bool sequencer_editing_initialized_and_active(struct bContext *C); /* UNUSED */ /* bool sequencer_strip_poll(struct bContext *C); */ bool sequencer_strip_has_path_poll(struct bContext *C); diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c index 6ba1dcc5eb8..af0aa093e40 100644 --- a/source/blender/editors/space_sequencer/sequencer_scopes.c +++ b/source/blender/editors/space_sequencer/sequencer_scopes.c @@ -17,7 +17,7 @@ #include "sequencer_intern.h" -/* XXX(campbell): why is this function better than BLI_math version? +/* XXX(@campbellbarton): why is this function better than BLI_math version? * only difference is it does some normalize after, need to double check on this. */ static void rgb_to_yuv_normalized(const float rgb[3], float yuv[3]) { diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index f237fbc0a12..4aaa3aeb2ff 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -59,7 +59,7 @@ SeqCollection *all_strips_from_context(bContext *C) const bool is_preview = sequencer_view_has_preview_poll(C); if (is_preview) { - return SEQ_query_rendered_strips(channels, seqbase, scene->r.cfra, 0); + return SEQ_query_rendered_strips(scene, channels, seqbase, scene->r.cfra, 0); } return SEQ_query_all_strips(seqbase); @@ -74,7 +74,7 @@ SeqCollection *selected_strips_from_context(bContext *C) const bool is_preview = sequencer_view_has_preview_poll(C); if (is_preview) { - SeqCollection *strips = SEQ_query_rendered_strips(channels, seqbase, scene->r.cfra, 0); + SeqCollection *strips = SEQ_query_rendered_strips(scene, channels, seqbase, scene->r.cfra, 0); SEQ_filter_selected_strips(strips); return strips; } @@ -108,7 +108,8 @@ static void select_surrounding_handles(Scene *scene, Sequence *test) /* XXX BRIN } /* Used for mouse selection in SEQUENCER_OT_select. */ -static void select_active_side(ListBase *seqbase, int sel_side, int channel, int frame) +static void select_active_side( + const Scene *scene, ListBase *seqbase, int sel_side, int channel, int frame) { Sequence *seq; @@ -116,13 +117,13 @@ static void select_active_side(ListBase *seqbase, int sel_side, int channel, int if (channel == seq->machine) { switch (sel_side) { case SEQ_SIDE_LEFT: - if (frame > (SEQ_time_left_handle_frame_get(seq))) { + if (frame > (SEQ_time_left_handle_frame_get(scene, seq))) { seq->flag &= ~(SEQ_RIGHTSEL | SEQ_LEFTSEL); seq->flag |= SELECT; } break; case SEQ_SIDE_RIGHT: - if (frame < (SEQ_time_left_handle_frame_get(seq))) { + if (frame < (SEQ_time_left_handle_frame_get(scene, seq))) { seq->flag &= ~(SEQ_RIGHTSEL | SEQ_LEFTSEL); seq->flag |= SELECT; } @@ -137,7 +138,8 @@ static void select_active_side(ListBase *seqbase, int sel_side, int channel, int } /* Used for mouse selection in SEQUENCER_OT_select_side. */ -static void select_active_side_range(ListBase *seqbase, +static void select_active_side_range(const Scene *scene, + ListBase *seqbase, const int sel_side, const int frame_ranges[MAXSEQ], const int frame_ignore) @@ -152,13 +154,13 @@ static void select_active_side_range(ListBase *seqbase, } switch (sel_side) { case SEQ_SIDE_LEFT: - if (frame > (SEQ_time_left_handle_frame_get(seq))) { + if (frame > (SEQ_time_left_handle_frame_get(scene, seq))) { seq->flag &= ~(SEQ_RIGHTSEL | SEQ_LEFTSEL); seq->flag |= SELECT; } break; case SEQ_SIDE_RIGHT: - if (frame < (SEQ_time_left_handle_frame_get(seq))) { + if (frame < (SEQ_time_left_handle_frame_get(scene, seq))) { seq->flag &= ~(SEQ_RIGHTSEL | SEQ_LEFTSEL); seq->flag |= SELECT; } @@ -173,14 +175,14 @@ static void select_active_side_range(ListBase *seqbase, } /* Used for mouse selection in SEQUENCER_OT_select */ -static void select_linked_time(ListBase *seqbase, Sequence *seq_link) +static void select_linked_time(const Scene *scene, ListBase *seqbase, Sequence *seq_link) { Sequence *seq; for (seq = seqbase->first; seq; seq = seq->next) { if (seq_link->machine != seq->machine) { - int left_match = (SEQ_time_left_handle_frame_get(seq) == seq_link->startdisp) ? 1 : 0; - int right_match = (SEQ_time_right_handle_frame_get(seq) == seq_link->enddisp) ? 1 : 0; + int left_match = (SEQ_time_left_handle_frame_get(scene, seq) == seq_link->startdisp) ? 1 : 0; + int right_match = (SEQ_time_right_handle_frame_get(scene, seq) == seq_link->enddisp) ? 1 : 0; if (left_match && right_match) { /* Direct match, copy the selection settings. */ @@ -245,10 +247,10 @@ void ED_sequencer_select_sequence_single(Scene *scene, Sequence *seq, bool desel recurs_sel_seq(seq); } -void seq_rectf(Sequence *seq, rctf *rect) +void seq_rectf(const Scene *scene, Sequence *seq, rctf *rect) { - rect->xmin = SEQ_time_left_handle_frame_get(seq); - rect->xmax = SEQ_time_right_handle_frame_get(seq); + rect->xmin = SEQ_time_left_handle_frame_get(scene, seq); + rect->xmax = SEQ_time_right_handle_frame_get(scene, seq); rect->ymin = seq->machine + SEQ_STRIP_OFSBOTTOM; rect->ymax = seq->machine + SEQ_STRIP_OFSTOP; } @@ -273,12 +275,14 @@ Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int se (sel == 0 && (seq->flag & SELECT) == 0))) { switch (lr) { case SEQ_SIDE_LEFT: - if (SEQ_time_left_handle_frame_get(test) == (SEQ_time_right_handle_frame_get(seq))) { + if (SEQ_time_left_handle_frame_get(scene, test) == + (SEQ_time_right_handle_frame_get(scene, seq))) { return seq; } break; case SEQ_SIDE_RIGHT: - if (SEQ_time_right_handle_frame_get(test) == (SEQ_time_left_handle_frame_get(seq))) { + if (SEQ_time_right_handle_frame_get(scene, test) == + (SEQ_time_left_handle_frame_get(scene, seq))) { return seq; } break; @@ -311,18 +315,20 @@ Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[ while (seq) { if (seq->machine == (int)y) { /* Check for both normal strips, and strips that have been flipped horizontally. */ - if (((SEQ_time_left_handle_frame_get(seq) < SEQ_time_right_handle_frame_get(seq)) && - (SEQ_time_left_handle_frame_get(seq) <= x && - SEQ_time_right_handle_frame_get(seq) >= x)) || - ((SEQ_time_left_handle_frame_get(seq) > SEQ_time_right_handle_frame_get(seq)) && - (SEQ_time_left_handle_frame_get(seq) >= x && - SEQ_time_right_handle_frame_get(seq) <= x))) { + if (((SEQ_time_left_handle_frame_get(scene, seq) < + SEQ_time_right_handle_frame_get(scene, seq)) && + (SEQ_time_left_handle_frame_get(scene, seq) <= x && + SEQ_time_right_handle_frame_get(scene, seq) >= x)) || + ((SEQ_time_left_handle_frame_get(scene, seq) > + SEQ_time_right_handle_frame_get(scene, seq)) && + (SEQ_time_left_handle_frame_get(scene, seq) >= x && + SEQ_time_right_handle_frame_get(scene, seq) <= x))) { if (SEQ_transform_sequence_can_be_translated(seq)) { /* Clamp handles to defined size in pixel space. */ - handsize = 2.0f * sequence_handle_size_get_clamped(seq, pixelx); - displen = (float)abs(SEQ_time_left_handle_frame_get(seq) - - SEQ_time_right_handle_frame_get(seq)); + handsize = 2.0f * sequence_handle_size_get_clamped(scene, seq, pixelx); + displen = (float)abs(SEQ_time_left_handle_frame_get(scene, seq) - + SEQ_time_right_handle_frame_get(scene, seq)); /* Don't even try to grab the handles of small strips. */ if (displen / pixelx > 16) { @@ -337,10 +343,10 @@ Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[ CLAMP(handsize, 7 * pixelx, 30 * pixelx); } - if (handsize + SEQ_time_left_handle_frame_get(seq) >= x) { + if (handsize + SEQ_time_left_handle_frame_get(scene, seq) >= x) { *hand = SEQ_SIDE_LEFT; } - else if (-handsize + SEQ_time_right_handle_frame_get(seq) <= x) { + else if (-handsize + SEQ_time_right_handle_frame_get(scene, seq) <= x) { *hand = SEQ_SIDE_RIGHT; } } @@ -583,8 +589,10 @@ static void sequencer_select_side_of_frame(const bContext *C, const float x = UI_view2d_region_to_view_x(v2d, mval[0]); LISTBASE_FOREACH (Sequence *, seq_iter, SEQ_active_seqbase_get(ed)) { - if (((x < CFRA) && (SEQ_time_right_handle_frame_get(seq_iter) <= CFRA)) || - ((x >= CFRA) && (SEQ_time_left_handle_frame_get(seq_iter) >= CFRA))) { + if (((x < scene->r.cfra) && + (SEQ_time_right_handle_frame_get(scene, seq_iter) <= scene->r.cfra)) || + ((x >= scene->r.cfra) && + (SEQ_time_left_handle_frame_get(scene, seq_iter) >= scene->r.cfra))) { /* Select left or right. */ seq_iter->flag |= SELECT; recurs_sel_seq(seq_iter); @@ -597,8 +605,8 @@ static void sequencer_select_side_of_frame(const bContext *C, TimeMarker *tmarker; for (tmarker = scene->markers.first; tmarker; tmarker = tmarker->next) { - if (((x < CFRA) && (tmarker->frame <= CFRA)) || - ((x >= CFRA) && (tmarker->frame >= CFRA))) { + if (((x < scene->r.cfra) && (tmarker->frame <= scene->r.cfra)) || + ((x >= scene->r.cfra) && (tmarker->frame >= scene->r.cfra))) { tmarker->flag |= SELECT; } else { @@ -639,8 +647,11 @@ static void sequencer_select_linked_handle(const bContext *C, case SEQ_SIDE_LEFT: if ((seq->flag & SEQ_LEFTSEL) && (neighbor->flag & SEQ_RIGHTSEL)) { seq->flag |= SELECT; - select_active_side( - ed->seqbasep, SEQ_SIDE_LEFT, seq->machine, SEQ_time_left_handle_frame_get(seq)); + select_active_side(scene, + ed->seqbasep, + SEQ_SIDE_LEFT, + seq->machine, + SEQ_time_left_handle_frame_get(scene, seq)); } else { seq->flag |= SELECT; @@ -653,8 +664,11 @@ static void sequencer_select_linked_handle(const bContext *C, case SEQ_SIDE_RIGHT: if ((seq->flag & SEQ_RIGHTSEL) && (neighbor->flag & SEQ_LEFTSEL)) { seq->flag |= SELECT; - select_active_side( - ed->seqbasep, SEQ_SIDE_RIGHT, seq->machine, SEQ_time_left_handle_frame_get(seq)); + select_active_side(scene, + ed->seqbasep, + SEQ_SIDE_RIGHT, + seq->machine, + SEQ_time_left_handle_frame_get(scene, seq)); } else { seq->flag |= SELECT; @@ -669,7 +683,7 @@ static void sequencer_select_linked_handle(const bContext *C, else { select_active_side( - ed->seqbasep, sel_side, seq->machine, SEQ_time_left_handle_frame_get(seq)); + scene, ed->seqbasep, sel_side, seq->machine, SEQ_time_left_handle_frame_get(scene, seq)); } } } @@ -734,7 +748,7 @@ static Sequence *seq_select_seq_from_preview( const bool use_cycle = (!WM_cursor_test_motion_and_update(mval) || extend || toggle); SeqCollection *strips = SEQ_query_rendered_strips( - channels, seqbase, scene->r.cfra, sseq->chanshown); + scene, channels, seqbase, scene->r.cfra, sseq->chanshown); /* Allow strips this far from the closest center to be included. * This allows cycling over center points which are near enough @@ -921,7 +935,7 @@ static int sequencer_select_exec(bContext *C, wmOperator *op) ED_sequencer_deselect_all(scene); } sequencer_select_strip_impl(ed, seq, handle_clicked, extend, deselect, toggle); - select_linked_time(ed->seqbasep, seq); + select_linked_time(scene, ed->seqbasep, seq); sequencer_select_do_updates(C, scene); sequencer_select_set_active(scene, seq); return OPERATOR_FINISHED; @@ -1431,18 +1445,18 @@ static int sequencer_select_side_of_frame_exec(bContext *C, wmOperator *op) if (extend == false) { ED_sequencer_deselect_all(scene); } - const int timeline_frame = CFRA; + const int timeline_frame = scene->r.cfra; LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) { bool test = false; switch (side) { case -1: - test = (timeline_frame >= SEQ_time_right_handle_frame_get(seq)); + test = (timeline_frame >= SEQ_time_right_handle_frame_get(scene, seq)); break; case 1: - test = (timeline_frame <= SEQ_time_left_handle_frame_get(seq)); + test = (timeline_frame <= SEQ_time_left_handle_frame_get(scene, seq)); break; case 2: - test = SEQ_time_strip_intersects_frame(seq, timeline_frame); + test = SEQ_time_strip_intersects_frame(scene, seq, timeline_frame); break; } @@ -1513,10 +1527,10 @@ static int sequencer_select_side_exec(bContext *C, wmOperator *op) if (seq->flag & SELECT) { selected = true; if (sel_side == SEQ_SIDE_LEFT) { - *frame_limit_p = max_ii(*frame_limit_p, SEQ_time_left_handle_frame_get(seq)); + *frame_limit_p = max_ii(*frame_limit_p, SEQ_time_left_handle_frame_get(scene, seq)); } else { - *frame_limit_p = min_ii(*frame_limit_p, SEQ_time_left_handle_frame_get(seq)); + *frame_limit_p = min_ii(*frame_limit_p, SEQ_time_left_handle_frame_get(scene, seq)); } } } @@ -1525,7 +1539,7 @@ static int sequencer_select_side_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - select_active_side_range(ed->seqbasep, sel_side, frame_ranges, frame_init); + select_active_side_range(scene, ed->seqbasep, sel_side, frame_ranges, frame_init); ED_outliner_select_sync_from_sequence_tag(C); @@ -1595,7 +1609,7 @@ static void seq_box_select_seq_from_preview(const bContext *C, rctf *rect, const SpaceSeq *sseq = CTX_wm_space_seq(C); SeqCollection *strips = SEQ_query_rendered_strips( - channels, seqbase, scene->r.cfra, sseq->chanshown); + scene, channels, seqbase, scene->r.cfra, sseq->chanshown); Sequence *seq; SEQ_ITERATOR_FOREACH (seq, strips) { if (!seq_box_select_rect_image_isect(scene, seq, rect)) { @@ -1648,15 +1662,15 @@ static int sequencer_box_select_exec(bContext *C, wmOperator *op) LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) { rctf rq; - seq_rectf(seq, &rq); + seq_rectf(scene, seq, &rq); if (BLI_rctf_isect(&rq, &rectf, NULL)) { if (handles) { /* Get the handles draw size. */ float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask); - float handsize = sequence_handle_size_get_clamped(seq, pixelx); + float handsize = sequence_handle_size_get_clamped(scene, seq, pixelx); /* Right handle. */ - if (rectf.xmax > (SEQ_time_right_handle_frame_get(seq) - handsize)) { + if (rectf.xmax > (SEQ_time_right_handle_frame_get(scene, seq) - handsize)) { if (select) { seq->flag |= SELECT | SEQ_RIGHTSEL; } @@ -1669,7 +1683,7 @@ static int sequencer_box_select_exec(bContext *C, wmOperator *op) } } /* Left handle. */ - if (rectf.xmin < (SEQ_time_left_handle_frame_get(seq) + handsize)) { + if (rectf.xmin < (SEQ_time_left_handle_frame_get(scene, seq) + handsize)) { if (select) { seq->flag |= SELECT | SEQ_LEFTSEL; } @@ -1953,7 +1967,8 @@ static bool select_grouped_effect(SeqCollection *strips, return changed; } -static bool select_grouped_time_overlap(SeqCollection *strips, +static bool select_grouped_time_overlap(const Scene *scene, + SeqCollection *strips, ListBase *UNUSED(seqbase), Sequence *actseq) { @@ -1961,8 +1976,10 @@ static bool select_grouped_time_overlap(SeqCollection *strips, Sequence *seq; SEQ_ITERATOR_FOREACH (seq, strips) { - if (SEQ_time_left_handle_frame_get(seq) < SEQ_time_right_handle_frame_get(actseq) && - SEQ_time_right_handle_frame_get(seq) > SEQ_time_left_handle_frame_get(actseq)) { + if (SEQ_time_left_handle_frame_get(scene, seq) < + SEQ_time_right_handle_frame_get(scene, actseq) && + SEQ_time_right_handle_frame_get(scene, seq) > + SEQ_time_left_handle_frame_get(scene, actseq)) { seq->flag |= SELECT; changed = true; } @@ -1972,7 +1989,8 @@ static bool select_grouped_time_overlap(SeqCollection *strips, } /* Query strips that are in lower channel and intersect in time with seq_reference. */ -static void query_lower_channel_strips(Sequence *seq_reference, +static void query_lower_channel_strips(const Scene *scene, + Sequence *seq_reference, ListBase *seqbase, SeqCollection *collection) { @@ -1980,10 +1998,10 @@ static void query_lower_channel_strips(Sequence *seq_reference, if (seq_test->machine > seq_reference->machine) { continue; /* Not lower channel. */ } - if (SEQ_time_right_handle_frame_get(seq_test) <= - SEQ_time_left_handle_frame_get(seq_reference) || - SEQ_time_left_handle_frame_get(seq_test) >= - SEQ_time_right_handle_frame_get(seq_reference)) { + if (SEQ_time_right_handle_frame_get(scene, seq_test) <= + SEQ_time_left_handle_frame_get(scene, seq_reference) || + SEQ_time_left_handle_frame_get(scene, seq_test) >= + SEQ_time_right_handle_frame_get(scene, seq_reference)) { continue; /* Not intersecting in time. */ } SEQ_collection_append_strip(seq_test, collection); @@ -1992,7 +2010,8 @@ static void query_lower_channel_strips(Sequence *seq_reference, /* Select all strips within time range and with lower channel of initial selection. Then select * effect chains of these strips. */ -static bool select_grouped_effect_link(SeqCollection *strips, +static bool select_grouped_effect_link(const Scene *scene, + SeqCollection *strips, ListBase *seqbase, Sequence *UNUSED(actseq), const int UNUSED(channel)) @@ -2000,8 +2019,10 @@ static bool select_grouped_effect_link(SeqCollection *strips, /* Get collection of strips. */ SEQ_filter_selected_strips(strips); const int selected_strip_count = SEQ_collection_len(strips); - SEQ_collection_expand(seqbase, strips, query_lower_channel_strips); - SEQ_collection_expand(seqbase, strips, SEQ_query_strip_effect_chain); + // XXX this uses scene as arg, so it does not work with iterator :( I had thought about this, but + // expand function is just so useful... I can just add scene and inject it I guess..... + SEQ_collection_expand(scene, seqbase, strips, query_lower_channel_strips); + SEQ_collection_expand(scene, seqbase, strips, SEQ_query_strip_effect_chain); /* Check if other strips will be affected. */ const bool changed = SEQ_collection_len(strips) > selected_strip_count; @@ -2067,10 +2088,10 @@ static int sequencer_select_grouped_exec(bContext *C, wmOperator *op) changed |= select_grouped_effect(strips, seqbase, actseq, channel); break; case SEQ_SELECT_GROUP_EFFECT_LINK: - changed |= select_grouped_effect_link(strips, seqbase, actseq, channel); + changed |= select_grouped_effect_link(scene, strips, seqbase, actseq, channel); break; case SEQ_SELECT_GROUP_OVERLAP: - changed |= select_grouped_time_overlap(strips, seqbase, actseq); + changed |= select_grouped_time_overlap(scene, strips, seqbase, actseq); break; default: BLI_assert(0); diff --git a/source/blender/editors/space_sequencer/sequencer_thumbnails.c b/source/blender/editors/space_sequencer/sequencer_thumbnails.c index 984d3b1f374..a11b5663620 100644 --- a/source/blender/editors/space_sequencer/sequencer_thumbnails.c +++ b/source/blender/editors/space_sequencer/sequencer_thumbnails.c @@ -69,15 +69,16 @@ static void thumbnail_endjob(void *data) WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, tj->scene); } -static bool check_seq_need_thumbnails(Sequence *seq, rctf *view_area) +static bool check_seq_need_thumbnails(const Scene *scene, Sequence *seq, rctf *view_area) { if (!ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE)) { return false; } - if (min_ii(SEQ_time_left_handle_frame_get(seq), seq->start) > view_area->xmax) { + if (min_ii(SEQ_time_left_handle_frame_get(scene, seq), seq->start) > view_area->xmax) { return false; } - if (max_ii(SEQ_time_right_handle_frame_get(seq), seq->start + seq->len) < view_area->xmin) { + if (max_ii(SEQ_time_right_handle_frame_get(scene, seq), seq->start + seq->len) < + view_area->xmin) { return false; } if (seq->machine + 1.0f < view_area->ymin) { @@ -135,6 +136,7 @@ static void thumbnail_start_job(void *data, float *UNUSED(progress)) { ThumbnailDrawJob *tj = data; + const Scene *scene = tj->scene; float frame_step; GHashIterator gh_iter; @@ -145,7 +147,7 @@ static void thumbnail_start_job(void *data, Sequence *seq_orig = BLI_ghashIterator_getKey(&gh_iter); ThumbDataItem *val = BLI_ghash_lookup(tj->sequences_ghash, seq_orig); - if (check_seq_need_thumbnails(seq_orig, tj->view_area)) { + if (check_seq_need_thumbnails(scene, seq_orig, tj->view_area)) { seq_get_thumb_image_dimensions( val->seq_dupli, tj->pixelx, tj->pixely, &frame_step, tj->thumb_height, NULL, NULL); SEQ_render_thumbnails( @@ -161,7 +163,7 @@ static void thumbnail_start_job(void *data, Sequence *seq_orig = BLI_ghashIterator_getKey(&gh_iter); ThumbDataItem *val = BLI_ghash_lookup(tj->sequences_ghash, seq_orig); - if (check_seq_need_thumbnails(seq_orig, tj->view_area)) { + if (check_seq_need_thumbnails(scene, seq_orig, tj->view_area)) { seq_get_thumb_image_dimensions( val->seq_dupli, tj->pixelx, tj->pixely, &frame_step, tj->thumb_height, NULL, NULL); SEQ_render_thumbnails_base_set(&tj->context, val->seq_dupli, seq_orig, tj->view_area, stop); @@ -197,7 +199,7 @@ static GHash *sequencer_thumbnail_ghash_init(const bContext *C, View2D *v2d, Edi LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) { ThumbDataItem *val_need_update = BLI_ghash_lookup(thumb_data_hash, seq); - if (val_need_update == NULL && check_seq_need_thumbnails(seq, &v2d->cur)) { + if (val_need_update == NULL && check_seq_need_thumbnails(scene, seq, &v2d->cur)) { ThumbDataItem *val = MEM_callocN(sizeof(ThumbDataItem), "Thumbnail Hash Values"); val->seq_dupli = SEQ_sequence_dupli_recursive(scene, scene, NULL, seq, 0); val->scene = scene; @@ -206,7 +208,7 @@ static GHash *sequencer_thumbnail_ghash_init(const bContext *C, View2D *v2d, Edi else { if (val_need_update != NULL) { val_need_update->seq_dupli->start = seq->start; - val_need_update->seq_dupli->startdisp = SEQ_time_left_handle_frame_get(seq); + val_need_update->seq_dupli->startdisp = SEQ_time_left_handle_frame_get(scene, seq); } } } @@ -361,18 +363,20 @@ static int sequencer_thumbnail_closest_previous_frame_get(int timeline_frame, return best_frame; } -static int sequencer_thumbnail_closest_guaranteed_frame_get(Sequence *seq, int timeline_frame) +static int sequencer_thumbnail_closest_guaranteed_frame_get(struct Scene *scene, + Sequence *seq, + int timeline_frame) { - if (timeline_frame <= SEQ_time_left_handle_frame_get(seq)) { - return SEQ_time_left_handle_frame_get(seq); + if (timeline_frame <= SEQ_time_left_handle_frame_get(scene, seq)) { + return SEQ_time_left_handle_frame_get(scene, seq); } /* Set of "guaranteed" thumbnails. */ - const int frame_index = timeline_frame - SEQ_time_left_handle_frame_get(seq); - const int frame_step = SEQ_render_thumbnails_guaranteed_set_frame_step_get(seq); + const int frame_index = timeline_frame - SEQ_time_left_handle_frame_get(scene, seq); + const int frame_step = SEQ_render_thumbnails_guaranteed_set_frame_step_get(scene, seq); const int relative_base_frame = round_fl_to_int((frame_index / (float)frame_step)) * frame_step; const int nearest_guaranted_absolute_frame = relative_base_frame + - SEQ_time_left_handle_frame_get(seq); + SEQ_time_left_handle_frame_get(scene, seq); return nearest_guaranted_absolute_frame; } @@ -387,7 +391,8 @@ static ImBuf *sequencer_thumbnail_closest_from_memory(const SeqRenderData *conte previously_displayed); ImBuf *ibuf_previous = SEQ_get_thumbnail(context, seq, frame_previous, crop, clipped); - int frame_guaranteed = sequencer_thumbnail_closest_guaranteed_frame_get(seq, timeline_frame); + int frame_guaranteed = sequencer_thumbnail_closest_guaranteed_frame_get( + context->scene, seq, timeline_frame); ImBuf *ibuf_guaranteed = SEQ_get_thumbnail(context, seq, frame_guaranteed, crop, clipped); ImBuf *closest_in_memory = NULL; @@ -427,6 +432,11 @@ void draw_seq_strip_thumbnail(View2D *v2d, float image_height, image_width, thumb_width; rcti crop; + StripElem *se = seq->strip->stripdata; + if (se->orig_height == 0 || se->orig_width == 0) { + return; + } + /* If width of the strip too small ignore drawing thumbnails. */ if ((y2 - y1) / pixely <= 20 * U.dpi_fac) { return; @@ -445,14 +455,14 @@ void draw_seq_strip_thumbnail(View2D *v2d, float thumb_y_end = y1 + thumb_height; float cut_off = 0; - float upper_thumb_bound = SEQ_time_has_right_still_frames(seq) ? + float upper_thumb_bound = SEQ_time_has_right_still_frames(scene, seq) ? (seq->start + seq->len) : - SEQ_time_right_handle_frame_get(seq); + SEQ_time_right_handle_frame_get(scene, seq); if (seq->type == SEQ_TYPE_IMAGE) { - upper_thumb_bound = SEQ_time_right_handle_frame_get(seq); + upper_thumb_bound = SEQ_time_right_handle_frame_get(scene, seq); } - float timeline_frame = SEQ_render_thumbnail_first_frame_get(seq, thumb_width, &v2d->cur); + float timeline_frame = SEQ_render_thumbnail_first_frame_get(scene, seq, thumb_width, &v2d->cur); float thumb_x_end; GSet *last_displayed_thumbnails = last_displayed_thumbnails_list_ensure(C, seq); @@ -475,8 +485,8 @@ void draw_seq_strip_thumbnail(View2D *v2d, } /* Set the clipping bound to show the left handle moving over thumbs and not shift thumbs. */ - if (IN_RANGE_INCL(SEQ_time_left_handle_frame_get(seq), timeline_frame, thumb_x_end)) { - cut_off = SEQ_time_left_handle_frame_get(seq) - timeline_frame; + if (IN_RANGE_INCL(SEQ_time_left_handle_frame_get(scene, seq), timeline_frame, thumb_x_end)) { + cut_off = SEQ_time_left_handle_frame_get(scene, seq) - timeline_frame; clipped = true; } @@ -553,7 +563,7 @@ void draw_seq_strip_thumbnail(View2D *v2d, IMB_freeImBuf(ibuf); GPU_blend(GPU_BLEND_NONE); cut_off = 0; - timeline_frame = SEQ_render_thumbnail_next_frame_get(seq, timeline_frame, thumb_width); + timeline_frame = SEQ_render_thumbnail_next_frame_get(scene, seq, timeline_frame, thumb_width); } last_displayed_thumbnails_list_cleanup(last_displayed_thumbnails, timeline_frame, FLT_MAX); } diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index 857ca6d989b..78fa8c379d9 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -12,6 +12,7 @@ #include "DNA_scene_types.h" #include "BKE_context.h" +#include "BKE_scene.h" #include "WM_api.h" #include "WM_types.h" @@ -84,7 +85,7 @@ static int sequencer_view_all_exec(bContext *C, wmOperator *op) box.xmin = ms->disp_range[0] - 1; box.xmax = ms->disp_range[1] + 1; } - SEQ_timeline_expand_boundbox(SEQ_active_seqbase_get(ed), &box); + SEQ_timeline_expand_boundbox(scene, SEQ_active_seqbase_get(ed), &box); View2D *v2d = ®ion->v2d; rcti scrub_rect; @@ -174,8 +175,7 @@ static int sequencer_view_all_preview_exec(bContext *C, wmOperator *UNUSED(op)) seq_reset_imageofs(sseq); - imgwidth = (scene->r.size * scene->r.xsch) / 100; - imgheight = (scene->r.size * scene->r.ysch) / 100; + BKE_render_resolution(&scene->r, false, &imgwidth, &imgheight); /* Apply aspect, doesn't need to be that accurate. */ imgwidth = (int)(imgwidth * (scene->r.xasp / scene->r.yasp)); @@ -227,11 +227,11 @@ static int sequencer_view_zoom_ratio_exec(bContext *C, wmOperator *op) float ratio = RNA_float_get(op->ptr, "ratio"); - float winx = (int)(rd->size * rd->xsch) / 100; - float winy = (int)(rd->size * rd->ysch) / 100; + int winx, winy; + BKE_render_resolution(rd, false, &winx, &winy); - float facx = BLI_rcti_size_x(&v2d->mask) / winx; - float facy = BLI_rcti_size_y(&v2d->mask) / winy; + float facx = BLI_rcti_size_x(&v2d->mask) / (float)winx; + float facy = BLI_rcti_size_y(&v2d->mask) / (float)winy; BLI_rctf_resize(&v2d->cur, ceilf(winx * facx / ratio + 0.5f), ceilf(winy * facy / ratio + 0.5f)); @@ -306,8 +306,8 @@ static void seq_view_collection_rect_timeline(Scene *scene, SeqCollection *strip int xmargin = FPS; SEQ_ITERATOR_FOREACH (seq, strips) { - xmin = min_ii(xmin, SEQ_time_left_handle_frame_get(seq)); - xmax = max_ii(xmax, SEQ_time_right_handle_frame_get(seq)); + xmin = min_ii(xmin, SEQ_time_left_handle_frame_get(scene, seq)); + xmax = max_ii(xmax, SEQ_time_right_handle_frame_get(scene, seq)); ymin = min_ii(ymin, seq->machine); ymax = max_ii(ymax, seq->machine); @@ -373,7 +373,7 @@ void SEQUENCER_OT_view_selected(wmOperatorType *ot) /* Api callbacks. */ ot->exec = sequencer_view_selected_exec; - ot->poll = ED_operator_sequencer_active; + ot->poll = sequencer_editing_initialized_and_active; /* Flags. */ ot->flag = OPTYPE_REGISTER; diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index f95c5f196b6..538cfad14f5 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -374,7 +374,7 @@ static SpaceLink *sequencer_duplicate(SpaceLink *sl) static void sequencer_listener(const wmSpaceTypeListenerParams *params) { ScrArea *area = params->area; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* Context changes. */ switch (wmn->category) { @@ -548,7 +548,8 @@ static void sequencer_main_clamp_view(const bContext *C, ARegion *region) } View2D *v2d = ®ion->v2d; - Editing *ed = SEQ_editing_get(CTX_data_scene(C)); + Scene *scene = CTX_data_scene(C); + Editing *ed = SEQ_editing_get(scene); if (ed == NULL) { return; @@ -563,7 +564,7 @@ static void sequencer_main_clamp_view(const bContext *C, ARegion *region) /* Initialize default view with 7 channels, that are visible even if empty. */ rctf strip_boundbox; BLI_rctf_init(&strip_boundbox, 0.0f, 0.0f, 1.0f, 7.0f); - SEQ_timeline_expand_boundbox(ed->seqbasep, &strip_boundbox); + SEQ_timeline_expand_boundbox(scene, ed->seqbasep, &strip_boundbox); /* Clamp Y max. Scrubbing area height must be added, so strips aren't occluded. */ rcti scrub_rect; @@ -629,7 +630,7 @@ static void sequencer_main_region_view2d_changed(const bContext *C, ARegion *reg static void sequencer_main_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* Context changes. */ switch (wmn->category) { @@ -861,7 +862,7 @@ static void sequencer_preview_region_draw(const bContext *C, ARegion *region) static void sequencer_preview_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; WM_gizmomap_tag_refresh(region->gizmo_map); @@ -932,7 +933,7 @@ static void sequencer_buttons_region_draw(const bContext *C, ARegion *region) static void sequencer_buttons_region_listener(const wmRegionListenerParams *params) { ARegion *region = params->region; - wmNotifier *wmn = params->notifier; + const wmNotifier *wmn = params->notifier; /* Context changes. */ switch (wmn->category) { @@ -996,7 +997,7 @@ void ED_spacetype_sequencer(void) ARegionType *art; st->spaceid = SPACE_SEQ; - strncpy(st->name, "Sequencer", BKE_ST_MAXNAME); + STRNCPY(st->name, "Sequencer"); st->create = sequencer_create; st->free = sequencer_free; |