Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/editors/include/ED_transform.h15
-rw-r--r--source/blender/editors/include/UI_interface.h2
-rw-r--r--source/blender/editors/interface/interface_dropboxes.cc4
-rw-r--r--source/blender/editors/interface/interface_ops.c2
-rw-r--r--source/blender/editors/screen/screen_ops.c2
-rw-r--r--source/blender/editors/space_clip/space_clip.c2
-rw-r--r--source/blender/editors/space_console/space_console.c4
-rw-r--r--source/blender/editors/space_file/space_file.c2
-rw-r--r--source/blender/editors/space_image/space_image.c2
-rw-r--r--source/blender/editors/space_node/space_node.cc6
-rw-r--r--source/blender/editors/space_sequencer/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c143
-rw-r--r--source/blender/editors/space_sequencer/sequencer_drag_drop.c650
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h5
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c131
-rw-r--r--source/blender/editors/space_text/space_text.c4
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c22
-rw-r--r--source/blender/editors/transform/transform.h2
-rw-r--r--source/blender/editors/transform/transform_convert.h2
-rw-r--r--source/blender/editors/transform/transform_convert_sequencer.c111
-rw-r--r--source/blender/editors/transform/transform_orientations.h2
-rw-r--r--source/blender/editors/transform/transform_snap_sequencer.c114
-rw-r--r--source/blender/sequencer/SEQ_transform.h5
-rw-r--r--source/blender/windowmanager/WM_api.h3
-rw-r--r--source/blender/windowmanager/WM_types.h29
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c55
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c1
27 files changed, 1062 insertions, 259 deletions
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index 66c17ff8115..82cc518f029 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -202,6 +202,21 @@ int ED_transform_calc_gizmo_stats(const struct bContext *C,
const struct TransformCalcParams *params,
struct TransformBounds *tbounds);
+/**
+ * Iterates over all the strips and finds the closest snapping candidate of either \a frame_1 or \a
+ * frame_2. The closest snapping candidate will be the closest start or end frame of an existing
+ * strip.
+ * \returns True if there was anything to snap to.
+ */
+bool ED_transform_snap_sequencer_to_closest_strip_calc(struct Scene *scene,
+ struct ARegion *region,
+ int frame_1,
+ int frame_2,
+ int *r_snap_distance,
+ float *r_snap_frame);
+
+void ED_draw_sequencer_snap_point(struct bContext *C, float snap_point);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 1b817d06564..9f4d6815287 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -2925,7 +2925,7 @@ void ED_keymap_ui(struct wmKeyConfig *keyconf);
void ED_dropboxes_ui(void);
void ED_uilisttypes_ui(void);
-void UI_drop_color_copy(struct wmDrag *drag, struct wmDropBox *drop);
+void UI_drop_color_copy(struct bContext *C, struct wmDrag *drag, struct wmDropBox *drop);
bool UI_drop_color_poll(struct bContext *C, struct wmDrag *drag, const struct wmEvent *event);
bool UI_context_copy_to_selected_list(struct bContext *C,
diff --git a/source/blender/editors/interface/interface_dropboxes.cc b/source/blender/editors/interface/interface_dropboxes.cc
index 2e8708827e7..9d3c1372b15 100644
--- a/source/blender/editors/interface/interface_dropboxes.cc
+++ b/source/blender/editors/interface/interface_dropboxes.cc
@@ -67,7 +67,7 @@ static bool ui_drop_name_poll(struct bContext *C, wmDrag *drag, const wmEvent *U
return UI_but_active_drop_name(C) && (drag->type == WM_DRAG_ID);
}
-static void ui_drop_name_copy(wmDrag *drag, wmDropBox *drop)
+static void ui_drop_name_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
const ID *id = WM_drag_get_local_ID(drag, 0);
RNA_string_set(drop->ptr, "string", id->name + 2);
@@ -85,7 +85,7 @@ static bool ui_drop_material_poll(bContext *C, wmDrag *drag, const wmEvent *UNUS
return WM_drag_is_ID_type(drag, ID_MA) && !RNA_pointer_is_null(&mat_slot);
}
-static void ui_drop_material_copy(wmDrag *drag, wmDropBox *drop)
+static void ui_drop_material_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
const ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, ID_MA);
RNA_int_set(drop->ptr, "session_uuid", (int)id->session_uuid);
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 0f4f0ef48ff..5b97a80d513 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -1862,7 +1862,7 @@ bool UI_drop_color_poll(struct bContext *C, wmDrag *drag, const wmEvent *UNUSED(
return 0;
}
-void UI_drop_color_copy(wmDrag *drag, wmDropBox *drop)
+void UI_drop_color_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
uiDragColorHandle *drag_info = drag->poin;
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 408ddfe7241..d7cf09ca89a 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -5771,7 +5771,7 @@ static bool blend_file_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEven
return false;
}
-static void blend_file_drop_copy(wmDrag *drag, wmDropBox *drop)
+static void blend_file_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
/* copy drag path to properties */
RNA_string_set(drop->ptr, "filepath", drag->path);
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index 444ed421083..91fef23019c 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -597,7 +597,7 @@ static bool clip_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNU
return false;
}
-static void clip_drop_copy(wmDrag *drag, wmDropBox *drop)
+static void clip_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
PointerRNA itemptr;
char dir[FILE_MAX], file[FILE_MAX];
diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c
index 8e33f7fa97f..c69b73e377d 100644
--- a/source/blender/editors/space_console/space_console.c
+++ b/source/blender/editors/space_console/space_console.c
@@ -149,7 +149,7 @@ static bool id_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSE
return WM_drag_get_local_ID(drag, 0) != NULL;
}
-static void id_drop_copy(wmDrag *drag, wmDropBox *drop)
+static void id_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
ID *id = WM_drag_get_local_ID(drag, 0);
@@ -164,7 +164,7 @@ static bool path_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNU
return (drag->type == WM_DRAG_PATH);
}
-static void path_drop_copy(wmDrag *drag, wmDropBox *drop)
+static void path_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
char pathname[FILE_MAX + 2];
BLI_snprintf(pathname, sizeof(pathname), "\"%s\"", drag->path);
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 7b3b87f4572..0170361f244 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -844,7 +844,7 @@ static bool filepath_drop_poll(bContext *C, wmDrag *drag, const wmEvent *UNUSED(
return false;
}
-static void filepath_drop_copy(wmDrag *drag, wmDropBox *drop)
+static void filepath_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
RNA_string_set(drop->ptr, "filepath", drag->path);
}
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index bc047a00ae1..568bd064e3e 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -255,7 +255,7 @@ static bool image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
return false;
}
-static void image_drop_copy(wmDrag *drag, wmDropBox *drop)
+static void image_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
/* copy drag path to properties */
RNA_string_set(drop->ptr, "filepath", drag->path);
diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc
index 82b850653be..34f357ae5c3 100644
--- a/source/blender/editors/space_node/space_node.cc
+++ b/source/blender/editors/space_node/space_node.cc
@@ -636,21 +636,21 @@ static bool node_mask_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent
return WM_drag_is_ID_type(drag, ID_MSK);
}
-static void node_group_drop_copy(wmDrag *drag, wmDropBox *drop)
+static void node_group_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0);
RNA_string_set(drop->ptr, "name", id->name + 2);
}
-static void node_id_drop_copy(wmDrag *drag, wmDropBox *drop)
+static void node_id_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0);
RNA_int_set(drop->ptr, "session_uuid", (int)id->session_uuid);
}
-static void node_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
+static void node_id_path_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0);
diff --git a/source/blender/editors/space_sequencer/CMakeLists.txt b/source/blender/editors/space_sequencer/CMakeLists.txt
index 2d1785523d7..b5355efec7a 100644
--- a/source/blender/editors/space_sequencer/CMakeLists.txt
+++ b/source/blender/editors/space_sequencer/CMakeLists.txt
@@ -25,6 +25,7 @@ set(INC
set(SRC
sequencer_add.c
sequencer_buttons.c
+ sequencer_drag_drop.c
sequencer_draw.c
sequencer_channels_draw.c
sequencer_channels_edit.c
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index 4672961543f..9298eb83b46 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -125,12 +125,20 @@ static void sequencer_generic_props__internal(wmOperatorType *ot, int flag)
ot->srna, "channel", 1, 1, MAXSEQ, "Channel", "Channel to place this strip into", 1, MAXSEQ);
RNA_def_boolean(
- ot->srna, "replace_sel", 1, "Replace Selection", "Replace the current selection");
+ ot->srna, "replace_sel", true, "Replace Selection", "Replace the current selection");
/* Only for python scripts which import strips and place them after. */
prop = RNA_def_boolean(
- ot->srna, "overlap", 0, "Allow Overlap", "Don't correct overlap on new sequence strips");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ ot->srna, "overlap", false, "Allow Overlap", "Don't correct overlap on new sequence strips");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(
+ ot->srna,
+ "overlap_shuffle_override",
+ false,
+ "Override Overlap Shuffle Behaviour",
+ "Use the overlap_mode tool settings to determine how to shuffle overlapping strips");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
if (flag & SEQPROP_FIT_METHOD) {
ot->prop = RNA_def_enum(ot->srna,
@@ -205,10 +213,13 @@ static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, i
RNA_int_set(op->ptr, "channel", sequencer_generic_invoke_xy_guess_channel(C, type));
}
- RNA_int_set(op->ptr, "frame_start", timeline_frame);
+ if (!RNA_struct_property_is_set(op->ptr, "frame_start")) {
+ RNA_int_set(op->ptr, "frame_start", timeline_frame);
+ }
if ((flag & SEQPROP_ENDFRAME) && RNA_struct_property_is_set(op->ptr, "frame_end") == 0) {
- RNA_int_set(op->ptr, "frame_end", timeline_frame + 25); /* XXX arbitrary but ok for now. */
+ RNA_int_set(
+ op->ptr, "frame_end", RNA_int_get(op->ptr, "frame_start") + DEFAULT_IMG_STRIP_LENGTH);
}
if (!(flag & SEQPROP_NOPATHS)) {
@@ -312,13 +323,53 @@ static void seq_load_apply_generic_options(bContext *C, wmOperator *op, Sequence
SEQ_select_active_set(scene, seq);
}
- if (RNA_boolean_get(op->ptr, "overlap") == false) {
- if (SEQ_transform_test_overlap(ed->seqbasep, seq)) {
- SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene);
- }
+ if (RNA_boolean_get(op->ptr, "overlap") == true ||
+ !SEQ_transform_test_overlap(ed->seqbasep, seq)) {
+ /* No overlap should be handled or the strip is not overlapping, exit early. */
+ return;
+ }
+
+ if (RNA_boolean_get(op->ptr, "overlap_shuffle_override")) {
+ /* Use set overlap_mode to fix overlaps. */
+ SeqCollection *strip_col = SEQ_collection_create(__func__);
+ SEQ_collection_append_strip(seq, strip_col);
+
+ ScrArea *area = CTX_wm_area(C);
+ const bool use_sync_markers = (((SpaceSeq *)area->spacedata.first)->flag & SEQ_MARKER_TRANS) !=
+ 0;
+ SEQ_transform_handle_overlap(scene, ed->seqbasep, strip_col, use_sync_markers);
+
+ SEQ_collection_free(strip_col);
+ }
+ else {
+ /* Shuffle strip channel to fix overlaps. */
+ SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene);
}
}
+/* In this alternative version we only check for overlap, but do not do anything about them. */
+static bool seq_load_apply_generic_options_only_test_overlap(bContext *C,
+ wmOperator *op,
+ Sequence *seq,
+ SeqCollection *strip_col)
+{
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = SEQ_editing_get(scene);
+
+ if (seq == NULL) {
+ return false;
+ }
+
+ if (RNA_boolean_get(op->ptr, "replace_sel")) {
+ seq->flag |= SELECT;
+ SEQ_select_active_set(scene, seq);
+ }
+
+ SEQ_collection_append_strip(seq, strip_col);
+
+ return SEQ_transform_test_overlap(ed->seqbasep, seq);
+}
+
static bool seq_effect_add_properties_poll(const bContext *UNUSED(C),
wmOperator *op,
const PropertyRNA *prop)
@@ -634,6 +685,14 @@ static void sequencer_add_movie_multiple_strips(bContext *C,
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
const Editing *ed = SEQ_editing_ensure(scene);
+ bool overlap_shuffle_override = RNA_boolean_get(op->ptr, "overlap") == false &&
+ RNA_boolean_get(op->ptr, "overlap_shuffle_override");
+ bool has_seq_overlap = false;
+ SeqCollection *strip_col = NULL;
+
+ if (overlap_shuffle_override) {
+ strip_col = SEQ_collection_create(__func__);
+ }
RNA_BEGIN (op->ptr, itemptr, "files") {
char dir_only[FILE_MAX];
@@ -645,9 +704,8 @@ static void sequencer_add_movie_multiple_strips(bContext *C,
Sequence *seq_movie = NULL;
Sequence *seq_sound = NULL;
- load_data->channel++;
seq_movie = SEQ_add_movie_strip(bmain, scene, ed->seqbasep, load_data);
- load_data->channel--;
+
if (seq_movie == NULL) {
BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
}
@@ -655,15 +713,40 @@ static void sequencer_add_movie_multiple_strips(bContext *C,
if (RNA_boolean_get(op->ptr, "sound")) {
seq_sound = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data);
sequencer_add_movie_clamp_sound_strip_length(scene, ed->seqbasep, seq_movie, seq_sound);
+
+ if (seq_sound) {
+ /* The video has sound, shift the video strip up a channel to make room for the sound
+ * strip. */
+ seq_movie->machine++;
+ }
}
load_data->start_frame += seq_movie->enddisp - seq_movie->startdisp;
- seq_load_apply_generic_options(C, op, seq_sound);
- seq_load_apply_generic_options(C, op, seq_movie);
+ if (overlap_shuffle_override) {
+ has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap(
+ C, op, seq_sound, strip_col);
+ has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap(
+ C, op, seq_movie, strip_col);
+ }
+ else {
+ seq_load_apply_generic_options(C, op, seq_sound);
+ seq_load_apply_generic_options(C, op, seq_movie);
+ }
SEQ_collection_append_strip(seq_movie, r_movie_strips);
}
}
RNA_END;
+
+ if (overlap_shuffle_override) {
+ if (has_seq_overlap) {
+ ScrArea *area = CTX_wm_area(C);
+ const bool use_sync_markers = (((SpaceSeq *)area->spacedata.first)->flag &
+ SEQ_MARKER_TRANS) != 0;
+ SEQ_transform_handle_overlap(scene, ed->seqbasep, strip_col, use_sync_markers);
+ }
+
+ SEQ_collection_free(strip_col);
+ }
}
static bool sequencer_add_movie_single_strip(bContext *C,
@@ -678,9 +761,7 @@ static bool sequencer_add_movie_single_strip(bContext *C,
Sequence *seq_movie = NULL;
Sequence *seq_sound = NULL;
- load_data->channel++;
seq_movie = SEQ_add_movie_strip(bmain, scene, ed->seqbasep, load_data);
- load_data->channel--;
if (seq_movie == NULL) {
BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
@@ -689,9 +770,37 @@ static bool sequencer_add_movie_single_strip(bContext *C,
if (RNA_boolean_get(op->ptr, "sound")) {
seq_sound = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data);
sequencer_add_movie_clamp_sound_strip_length(scene, ed->seqbasep, seq_movie, seq_sound);
+ if (seq_sound) {
+ /* The video has sound, shift the video strip up a channel to make room for the sound
+ * strip. */
+ seq_movie->machine++;
+ }
+ }
+
+ bool overlap_shuffle_override = RNA_boolean_get(op->ptr, "overlap") == false &&
+ RNA_boolean_get(op->ptr, "overlap_shuffle_override");
+ if (overlap_shuffle_override) {
+ SeqCollection *strip_col = SEQ_collection_create(__func__);
+ bool has_seq_overlap = false;
+
+ has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap(
+ C, op, seq_sound, strip_col);
+ has_seq_overlap |= seq_load_apply_generic_options_only_test_overlap(
+ C, op, seq_movie, strip_col);
+
+ if (has_seq_overlap) {
+ ScrArea *area = CTX_wm_area(C);
+ const bool use_sync_markers = (((SpaceSeq *)area->spacedata.first)->flag &
+ SEQ_MARKER_TRANS) != 0;
+ SEQ_transform_handle_overlap(scene, ed->seqbasep, strip_col, use_sync_markers);
+ }
+
+ SEQ_collection_free(strip_col);
+ }
+ else {
+ seq_load_apply_generic_options(C, op, seq_sound);
+ seq_load_apply_generic_options(C, op, seq_movie);
}
- seq_load_apply_generic_options(C, op, seq_sound);
- seq_load_apply_generic_options(C, op, seq_movie);
SEQ_collection_append_strip(seq_movie, r_movie_strips);
return true;
diff --git a/source/blender/editors/space_sequencer/sequencer_drag_drop.c b/source/blender/editors/space_sequencer/sequencer_drag_drop.c
new file mode 100644
index 00000000000..639d3651714
--- /dev/null
+++ b/source/blender/editors/space_sequencer/sequencer_drag_drop.c
@@ -0,0 +1,650 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup spseq
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_sound_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_string_utils.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_main.h"
+
+#include "SEQ_channels.h"
+#include "SEQ_iterator.h"
+#include "SEQ_sequencer.h"
+#include "SEQ_transform.h"
+
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+
+#include "ED_screen.h"
+#include "ED_transform.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/* For querying audio files. */
+#ifdef WITH_AUDASPACE
+# include "BKE_sound.h"
+# include <AUD_Sound.h>
+# include <AUD_Special.h>
+#endif
+
+/* Own include. */
+#include "sequencer_intern.h"
+
+typedef struct SeqDropCoords {
+ float start_frame, channel;
+ int strip_len, channel_len;
+ bool in_use;
+ bool is_intersecting;
+ bool use_snapping;
+ float snap_point_x;
+ uint8_t type;
+} SeqDropCoords;
+
+/* The current drag and drop API doesn't allow us to easily pass along the
+ * required custom data to all callbacks that need it. Especially when
+ * 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 void generic_poll_operations(const wmEvent *event, uint8_t type)
+{
+ g_drop_coords.type = type;
+ /* We purposely ignore the snapping tool setting here as currently other drag&drop operators only
+ * snaps when holding down Ctrl. */
+ g_drop_coords.use_snapping = event->modifier & KM_CTRL;
+}
+
+static bool image_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *event)
+{
+ if (drag->type == WM_DRAG_PATH) {
+ if (ELEM(drag->icon, ICON_FILE_IMAGE, ICON_FILE_BLANK)) { /* Rule might not work? */
+ generic_poll_operations(event, TH_SEQ_IMAGE);
+ return true;
+ }
+ }
+
+ return WM_drag_is_ID_type(drag, ID_IM);
+}
+
+static bool movie_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *event)
+{
+ 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);
+ return true;
+ }
+ }
+
+ return WM_drag_is_ID_type(drag, ID_MC);
+}
+
+static bool sound_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *event)
+{
+ 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;
+ }
+ }
+
+ return WM_drag_is_ID_type(drag, ID_SO);
+}
+
+static void sequencer_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop)
+{
+ 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;
+ PointerRNA itemptr;
+ char dir[FILE_MAX], file[FILE_MAX];
+ BLI_split_dirfile(ima->filepath, dir, file, sizeof(dir), sizeof(file));
+ RNA_string_set(drop->ptr, "directory", dir);
+ RNA_collection_clear(drop->ptr, "files");
+ RNA_collection_add(drop->ptr, "files", &itemptr);
+ RNA_string_set(&itemptr, "name", file);
+ }
+ else if (id_type == ID_MC) {
+ MovieClip *clip = (MovieClip *)id;
+ RNA_string_set(drop->ptr, "filepath", clip->filepath);
+ RNA_struct_property_unset(drop->ptr, "name");
+ }
+ else if (id_type == ID_SO) {
+ bSound *sound = (bSound *)id;
+ RNA_string_set(drop->ptr, "filepath", sound->filepath);
+ RNA_struct_property_unset(drop->ptr, "name");
+ }
+ }
+ /* Path dropped. */
+ else if (drag->path[0]) {
+ if (RNA_struct_find_property(drop->ptr, "filepath")) {
+ RNA_string_set(drop->ptr, "filepath", drag->path);
+ }
+ if (RNA_struct_find_property(drop->ptr, "directory")) {
+ PointerRNA itemptr;
+ char dir[FILE_MAX], file[FILE_MAX];
+
+ BLI_split_dirfile(drag->path, dir, file, sizeof(dir), sizeof(file));
+
+ RNA_string_set(drop->ptr, "directory", dir);
+
+ RNA_collection_clear(drop->ptr, "files");
+ 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 = &region->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 = coords->start_frame + coords->strip_len;
+
+ if (coords->use_snapping) {
+ /* Do snapping via the exsiting 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 + coords->strip_len;
+ coords->snap_point_x = snap_frame;
+ }
+ else {
+ /* Nothing was snapped to, disable snap drawing. */
+ coords->use_snapping = false;
+ }
+ }
+
+ if (coords->strip_len < 1) {
+ /* Only check if there is a strip already under the mouse cursor. */
+ coords->is_intersecting = find_nearest_seq(scene, &region->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,
+ .startdisp = coords->start_frame,
+ .enddisp = coords->start_frame + 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++;
+ }
+ }
+}
+
+static void draw_seq_in_view(bContext *C, wmWindow *UNUSED(win), wmDrag *drag, const int xy[2])
+{
+ SeqDropCoords *coords = &g_drop_coords;
+ if (!coords->in_use) {
+ return;
+ }
+
+ 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_poistion_data(C, mval);
+
+ GPU_matrix_push();
+ UI_view2d_view_ortho(&region->v2d);
+
+ /* Sometimes the active theme is not the sequencer theme, e.g. when an operator invokes the
+ * file browser. This makes sure we get the right color values for the theme. */
+ struct bThemeState theme_state;
+ UI_Theme_Store(&theme_state);
+ UI_SetTheme(SPACE_SEQ, RGN_TYPE_WINDOW);
+
+ if (coords->use_snapping) {
+ ED_draw_sequencer_snap_point(C, coords->snap_point_x);
+ }
+
+ /* Init GPU drawing. */
+ GPU_line_width(2.0f);
+ 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);
+
+ /* Draw strips. The code here is taken from sequencer_draw. */
+ float x1 = coords->start_frame;
+ float x2 = coords->start_frame + coords->strip_len;
+ float strip_color[3];
+ uchar text_color[4] = {255, 255, 255, 255};
+ float pixelx = BLI_rctf_size_x(&region->v2d.cur) / BLI_rcti_size_x(&region->v2d.mask);
+ float pixely = BLI_rctf_size_y(&region->v2d.cur) / BLI_rcti_size_y(&region->v2d.mask);
+
+ for (int i = 0; i < coords->channel_len; i++) {
+ float y1 = floorf(coords->channel) + i + SEQ_STRIP_OFSBOTTOM;
+ float y2 = floorf(coords->channel) + i + SEQ_STRIP_OFSTOP;
+
+ if (coords->type == TH_SEQ_MOVIE && i == 0 && coords->channel_len > 1) {
+ /* Assume only video strips occupies two channels.
+ * One for video and the other for audio.
+ * The audio channel is added first.
+ */
+ UI_GetThemeColor3fv(TH_SEQ_AUDIO, strip_color);
+ }
+ else {
+ UI_GetThemeColor3fv(coords->type, strip_color);
+ }
+
+ immUniformColor3fvAlpha(strip_color, 0.8f);
+ immRectf(pos, x1, y1, x2, y2);
+
+ if (coords->is_intersecting) {
+ strip_color[0] = 1.0f;
+ strip_color[1] = strip_color[2] = 0.3f;
+ }
+ else {
+ if (coords->channel_len - 1 == i) {
+ text_color[0] = text_color[1] = text_color[2] = 255;
+ UI_GetThemeColor3fv(TH_SEQ_ACTIVE, strip_color);
+ }
+ else {
+ text_color[0] = text_color[1] = text_color[2] = 10;
+ UI_GetThemeColor3fv(TH_SEQ_SELECTED, strip_color);
+ }
+ }
+
+ /* Draw a 2 pixel border around the strip. */
+ immUniformColor3fvAlpha(strip_color, 0.8f);
+ /* Left */
+ immRectf(pos, x1 - pixelx, y1, x1 + pixelx, y2);
+ /* Bottom */
+ immRectf(pos, x1 - pixelx, y1, x2 + pixelx, y1 + 2 * pixely);
+ /* Right */
+ immRectf(pos, x2 - pixelx, y1, x2 + pixelx, y2);
+ /* Top */
+ immRectf(pos, x1 - pixelx, y2 - 2 * pixely, x2 + pixelx, y2);
+
+ float handle_size = 8.0f; /* SEQ_HANDLE_SIZE */
+
+ /* Calculate height needed for drawing text on strip. */
+ float text_margin_y = y2 - min_ff(0.40f, 20 * U.dpi_fac * pixely);
+ float text_margin_x = 2.0f * (pixelx * handle_size) * U.pixelsize;
+
+ rctf rect;
+ rect.xmin = x1 + text_margin_x;
+ rect.ymin = text_margin_y;
+ rect.xmax = x2 - text_margin_x;
+ rect.ymax = y2;
+
+ if (rect.xmax <= rect.xmin) {
+ /* Exit early and skip text drawing if the strip doesn't have any space to put the text
+ * into.
+ */
+ break;
+ }
+
+ SpaceSeq *sseq = CTX_wm_space_seq(C);
+ const char *text_sep = " | ";
+ const char *text_array[5];
+ char text_display[FILE_MAX];
+ char filename[FILE_MAX];
+ char rel_path[FILE_MAX];
+ char strip_duration_text[16];
+ int len_text_arr = 0;
+
+ if (sseq->timeline_overlay.flag & SEQ_TIMELINE_SHOW_STRIP_NAME) {
+ BLI_split_file_part(drag->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));
+ text_array[len_text_arr++] = text_sep;
+ text_array[len_text_arr++] = rel_path;
+ }
+
+ if (sseq->timeline_overlay.flag & SEQ_TIMELINE_SHOW_STRIP_DURATION) {
+ SNPRINTF(strip_duration_text, "%d", (int)(x2 - x1));
+ text_array[len_text_arr++] = text_sep;
+ text_array[len_text_arr++] = strip_duration_text;
+ }
+
+ BLI_assert(len_text_arr <= ARRAY_SIZE(text_array));
+
+ BLI_string_join_array(text_display, FILE_MAX, text_array, len_text_arr);
+
+ UI_view2d_text_cache_add_rectf(
+ &region->v2d, &rect, text_display, strlen(text_display), text_color);
+ }
+
+ /* Clean after drawing up. */
+ UI_Theme_Restore(&theme_state);
+ GPU_matrix_pop();
+ immUnbindProgram();
+ GPU_blend(GPU_BLEND_NONE);
+ GPU_line_smooth(false);
+
+ UI_view2d_text_cache_draw(region);
+}
+
+static bool generic_drop_draw_handling(struct wmDropBox *drop)
+{
+ SeqDropCoords *coords = drop->draw_data;
+ if (coords && coords->in_use) {
+ return true;
+ }
+
+ coords = drop->draw_data = &g_drop_coords;
+ coords->in_use = true;
+
+ return false;
+}
+
+typedef struct DropJobData {
+ char path[FILE_MAX];
+ bool only_audio;
+ float scene_fps;
+} DropJobData;
+
+static void prefetch_data_fn(void *custom_data,
+ short *UNUSED(stop),
+ short *UNUSED(do_update),
+ float *UNUSED(progress))
+{
+ DropJobData *job_data = (DropJobData *)custom_data;
+
+ if (job_data->only_audio) {
+#ifdef WITH_AUDASPACE
+ /* Get the sound file length */
+ AUD_Sound *sound = AUD_Sound_file(job_data->path);
+ if (sound != NULL) {
+
+ AUD_SoundInfo info = AUD_getInfo(sound);
+ if ((eSoundChannels)info.specs.channels != SOUND_CHANNELS_INVALID) {
+ g_drop_coords.strip_len = max_ii(1, round((info.length) * job_data->scene_fps));
+ }
+ AUD_Sound_free(sound);
+ return;
+ }
+#endif
+ }
+
+ char colorspace[64] = "\0"; /* 64 == MAX_COLORSPACE_NAME length. */
+ struct anim *anim = openanim(job_data->path, IB_rect, 0, colorspace);
+
+ if (anim != NULL) {
+ g_drop_coords.strip_len = IMB_anim_get_duration(anim, IMB_TC_NONE);
+ IMB_free_anim(anim);
+#ifdef WITH_AUDASPACE
+ /* Try to load sound and see if the video has a sound channel. */
+ AUD_Sound *sound = AUD_Sound_file(job_data->path);
+ if (sound != NULL) {
+
+ AUD_SoundInfo info = AUD_getInfo(sound);
+ if ((eSoundChannels)info.specs.channels != SOUND_CHANNELS_INVALID) {
+ g_drop_coords.channel_len = 2;
+ }
+ AUD_Sound_free(sound);
+ }
+#endif
+ }
+}
+
+static void free_prefetch_data_fn(void *custom_data)
+{
+ DropJobData *job_data = (DropJobData *)custom_data;
+ MEM_freeN(job_data);
+}
+
+static void start_audio_video_job(bContext *C, char *path, bool only_audio)
+{
+ g_drop_coords.strip_len = 0;
+ g_drop_coords.channel_len = 1;
+
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+ Scene *scene = CTX_data_scene(C);
+
+ wmJob *wm_job = WM_jobs_get(
+ wm, win, NULL, "Load Previews", 0, WM_JOB_TYPE_SEQ_DRAG_DROP_PREVIEW);
+
+ DropJobData *job_data = (DropJobData *)MEM_mallocN(sizeof(DropJobData),
+ "SeqDragDropPreviewData");
+
+ BLI_strncpy(job_data->path, path, FILE_MAX);
+ job_data->only_audio = only_audio;
+ job_data->scene_fps = FPS;
+
+ WM_jobs_customdata_set(wm_job, job_data, free_prefetch_data_fn);
+ WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW);
+ WM_jobs_callbacks(wm_job, prefetch_data_fn, NULL, NULL, NULL);
+
+ WM_jobs_start(wm, wm_job);
+}
+
+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);
+ }
+}
+
+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);
+ }
+}
+
+static void movie_drop_draw_activate(struct wmDropBox *drop, wmDrag *UNUSED(drag))
+{
+ if (generic_drop_draw_handling(drop)) {
+ return;
+ }
+}
+
+static void sound_drop_draw_activate(struct wmDropBox *drop, wmDrag *UNUSED(drag))
+{
+ if (generic_drop_draw_handling(drop)) {
+ return;
+ }
+}
+
+static void image_drop_draw_activate(struct wmDropBox *drop, wmDrag *UNUSED(drag))
+{
+ if (generic_drop_draw_handling(drop)) {
+ return;
+ }
+
+ SeqDropCoords *coords = drop->draw_data;
+ coords->strip_len = DEFAULT_IMG_STRIP_LENGTH;
+ coords->channel_len = 1;
+}
+
+static void sequencer_drop_draw_deactivate(struct wmDropBox *drop, wmDrag *UNUSED(drag))
+{
+ SeqDropCoords *coords = drop->draw_data;
+ if (coords) {
+ coords->in_use = false;
+ drop->draw_data = NULL;
+ }
+}
+
+static void nop_draw_droptip_fn(bContext *UNUSED(C),
+ wmWindow *UNUSED(win),
+ wmDrag *UNUSED(drag),
+ const int UNUSED(xy[2]))
+{
+ /* Do nothing in here.
+ * This is to prevent the default drag and drop mouse overlay to be drawn.
+ */
+}
+
+/* This region dropbox definition. */
+static void sequencer_dropboxes_add_to_lb(ListBase *lb)
+{
+ struct wmDropBox *drop;
+ drop = WM_dropbox_add(
+ lb, "SEQUENCER_OT_image_strip_add", image_drop_poll, sequencer_drop_copy, NULL, NULL);
+ drop->draw_droptip = nop_draw_droptip_fn;
+ drop->draw_in_view = draw_seq_in_view;
+ drop->draw_activate = image_drop_draw_activate;
+ drop->draw_deactivate = sequencer_drop_draw_deactivate;
+
+ drop->on_drag_start = audio_prefetch;
+
+ drop = WM_dropbox_add(
+ lb, "SEQUENCER_OT_movie_strip_add", movie_drop_poll, sequencer_drop_copy, NULL, NULL);
+ drop->draw_droptip = nop_draw_droptip_fn;
+ drop->draw_in_view = draw_seq_in_view;
+ drop->draw_activate = movie_drop_draw_activate;
+ drop->draw_deactivate = sequencer_drop_draw_deactivate;
+
+ drop->on_drag_start = video_prefetch;
+
+ drop = WM_dropbox_add(
+ lb, "SEQUENCER_OT_sound_strip_add", sound_drop_poll, sequencer_drop_copy, NULL, NULL);
+ drop->draw_droptip = nop_draw_droptip_fn;
+ drop->draw_in_view = draw_seq_in_view;
+ drop->draw_activate = sound_drop_draw_activate;
+ drop->draw_deactivate = sequencer_drop_draw_deactivate;
+}
+
+static bool image_drop_preview_poll(bContext *UNUSED(C),
+ wmDrag *drag,
+ const wmEvent *UNUSED(event))
+{
+ if (drag->type == WM_DRAG_PATH) {
+ if (ELEM(drag->icon, ICON_FILE_IMAGE, ICON_FILE_BLANK)) { /* Rule might not work? */
+ return true;
+ }
+ }
+
+ return WM_drag_is_ID_type(drag, ID_IM);
+}
+
+static bool movie_drop_preview_poll(bContext *UNUSED(C),
+ wmDrag *drag,
+ const wmEvent *UNUSED(event))
+{
+ if (drag->type == WM_DRAG_PATH) {
+ if (ELEM(drag->icon, 0, ICON_FILE_MOVIE, ICON_FILE_BLANK)) { /* Rule might not work? */
+ return true;
+ }
+ }
+
+ return WM_drag_is_ID_type(drag, ID_MC);
+}
+
+static bool sound_drop_preview_poll(bContext *UNUSED(C),
+ wmDrag *drag,
+ const wmEvent *UNUSED(event))
+{
+ if (drag->type == WM_DRAG_PATH) {
+ if (ELEM(drag->icon, ICON_FILE_SOUND, ICON_FILE_BLANK)) { /* Rule might not work? */
+ return true;
+ }
+ }
+
+ return WM_drag_is_ID_type(drag, ID_SO);
+}
+
+static void sequencer_preview_dropboxes_add_to_lb(ListBase *lb)
+{
+ WM_dropbox_add(lb,
+ "SEQUENCER_OT_image_strip_add",
+ image_drop_preview_poll,
+ sequencer_drop_copy,
+ NULL,
+ NULL);
+
+ WM_dropbox_add(lb,
+ "SEQUENCER_OT_movie_strip_add",
+ movie_drop_preview_poll,
+ sequencer_drop_copy,
+ NULL,
+ NULL);
+
+ WM_dropbox_add(lb,
+ "SEQUENCER_OT_sound_strip_add",
+ sound_drop_preview_poll,
+ sequencer_drop_copy,
+ NULL,
+ NULL);
+}
+
+void sequencer_dropboxes(void)
+{
+ ListBase *lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
+ sequencer_dropboxes_add_to_lb(lb);
+ lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_PREVIEW);
+ sequencer_preview_dropboxes_add_to_lb(lb);
+}
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index 781aa521880..67df065ef35 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -29,6 +29,7 @@ struct ScrArea;
struct Editing;
struct ListBase;
+#define DEFAULT_IMG_STRIP_LENGTH 25 /* XXX arbitrary but ok for now. */
#define OVERLAP_ALPHA 180
typedef struct SeqChannelDrawContext {
@@ -237,6 +238,10 @@ void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot);
void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot);
void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot);
+/* sequencer_drag_drop.c */
+
+void sequencer_dropboxes(void);
+
/* sequencer_ops.c */
void sequencer_operatortypes(void);
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 89bff839481..ed669f5f8d2 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -9,20 +9,15 @@
#include <stdio.h>
#include <string.h>
-#include "DNA_gpencil_types.h"
#include "DNA_mask_types.h"
#include "DNA_scene_types.h"
-#include "DNA_sound_types.h"
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
-#include "BLI_utildefines.h"
-#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_lib_id.h"
#include "BKE_lib_remap.h"
#include "BKE_screen.h"
#include "BKE_sequencer_offscreen.h"
@@ -37,15 +32,11 @@
#include "WM_api.h"
#include "WM_message.h"
-#include "WM_types.h"
-
-#include "RNA_access.h"
#include "SEQ_transform.h"
#include "SEQ_utils.h"
#include "UI_interface.h"
-#include "UI_resources.h"
#include "UI_view2d.h"
#include "IMB_imbuf.h"
@@ -404,128 +395,6 @@ static void sequencer_listener(const wmSpaceTypeListenerParams *params)
}
}
-/* ************* dropboxes ************* */
-
-static bool image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
-{
- ARegion *region = CTX_wm_region(C);
- Scene *scene = CTX_data_scene(C);
- int hand;
-
- if (drag->type == WM_DRAG_PATH) {
- if (ELEM(drag->icon, ICON_FILE_IMAGE, ICON_FILE_BLANK)) { /* Rule might not work? */
- if (find_nearest_seq(scene, &region->v2d, &hand, event->mval) == NULL) {
- return 1;
- }
- }
- }
-
- return WM_drag_is_ID_type(drag, ID_IM);
-}
-
-static bool movie_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
-{
- ARegion *region = CTX_wm_region(C);
- Scene *scene = CTX_data_scene(C);
- int hand;
-
- if (drag->type == WM_DRAG_PATH) {
- if (ELEM(drag->icon, 0, ICON_FILE_MOVIE, ICON_FILE_BLANK)) { /* Rule might not work? */
- if (find_nearest_seq(scene, &region->v2d, &hand, event->mval) == NULL) {
- return 1;
- }
- }
- }
-
- return WM_drag_is_ID_type(drag, ID_MC);
-}
-
-static bool sound_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
-{
- ARegion *region = CTX_wm_region(C);
- Scene *scene = CTX_data_scene(C);
- int hand;
-
- if (drag->type == WM_DRAG_PATH) {
- if (ELEM(drag->icon, ICON_FILE_SOUND, ICON_FILE_BLANK)) { /* Rule might not work? */
- if (find_nearest_seq(scene, &region->v2d, &hand, event->mval) == NULL) {
- return 1;
- }
- }
- }
-
- return WM_drag_is_ID_type(drag, ID_SO);
-}
-
-static void sequencer_drop_copy(wmDrag *drag, wmDropBox *drop)
-{
- 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;
- PointerRNA itemptr;
- char dir[FILE_MAX], file[FILE_MAX];
- BLI_split_dirfile(ima->filepath, dir, file, sizeof(dir), sizeof(file));
- RNA_string_set(drop->ptr, "directory", dir);
- RNA_collection_clear(drop->ptr, "files");
- RNA_collection_add(drop->ptr, "files", &itemptr);
- RNA_string_set(&itemptr, "name", file);
- }
- else if (id_type == ID_MC) {
- MovieClip *clip = (MovieClip *)id;
- RNA_string_set(drop->ptr, "filepath", clip->filepath);
- RNA_struct_property_unset(drop->ptr, "name");
- }
- else if (id_type == ID_SO) {
- bSound *sound = (bSound *)id;
- RNA_string_set(drop->ptr, "filepath", sound->filepath);
- RNA_struct_property_unset(drop->ptr, "name");
- }
- }
- /* Path dropped. */
- else if (drag->path[0]) {
- if (RNA_struct_find_property(drop->ptr, "filepath")) {
- RNA_string_set(drop->ptr, "filepath", drag->path);
- }
- if (RNA_struct_find_property(drop->ptr, "directory")) {
- PointerRNA itemptr;
- char dir[FILE_MAX], file[FILE_MAX];
-
- BLI_split_dirfile(drag->path, dir, file, sizeof(dir), sizeof(file));
-
- RNA_string_set(drop->ptr, "directory", dir);
-
- RNA_collection_clear(drop->ptr, "files");
- RNA_collection_add(drop->ptr, "files", &itemptr);
- RNA_string_set(&itemptr, "name", file);
- }
- }
-}
-
-/* This region dropbox definition. */
-
-static void sequencer_dropboxes_add_to_lb(ListBase *lb)
-{
- WM_dropbox_add(
- lb, "SEQUENCER_OT_image_strip_add", image_drop_poll, sequencer_drop_copy, NULL, NULL);
- WM_dropbox_add(
- lb, "SEQUENCER_OT_movie_strip_add", movie_drop_poll, sequencer_drop_copy, NULL, NULL);
- WM_dropbox_add(
- lb, "SEQUENCER_OT_sound_strip_add", sound_drop_poll, sequencer_drop_copy, NULL, NULL);
-}
-
-static void sequencer_dropboxes(void)
-{
- ListBase *lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
- sequencer_dropboxes_add_to_lb(lb);
- lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_PREVIEW);
- sequencer_dropboxes_add_to_lb(lb);
-}
-
-/* ************* end drop *********** */
-
/* DO NOT make this static, this hides the symbol and breaks API generation script. */
extern const char *sequencer_context_dir[]; /* Quiet warning. */
const char *sequencer_context_dir[] = {"edit_mask", NULL};
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index 15353d610d1..ea35a8c0fa7 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -308,7 +308,7 @@ static bool text_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNU
return false;
}
-static void text_drop_copy(wmDrag *drag, wmDropBox *drop)
+static void text_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
/* copy drag path to properties */
RNA_string_set(drop->ptr, "filepath", drag->path);
@@ -319,7 +319,7 @@ static bool text_drop_paste_poll(bContext *UNUSED(C), wmDrag *drag, const wmEven
return (drag->type == WM_DRAG_ID);
}
-static void text_drop_paste(wmDrag *drag, wmDropBox *drop)
+static void text_drop_paste(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
char *text;
ID *id = WM_drag_get_local_ID(drag, 0);
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 1d22c2f237b..50d288af0e0 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -712,7 +712,7 @@ static void view3d_ob_drop_matrix_from_snap(V3DSnapCursorState *snap_state,
}
}
-static void view3d_ob_drop_copy_local_id(wmDrag *drag, wmDropBox *drop)
+static void view3d_ob_drop_copy_local_id(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
ID *id = WM_drag_get_local_ID(drag, ID_OB);
@@ -730,7 +730,7 @@ static void view3d_ob_drop_copy_local_id(wmDrag *drag, wmDropBox *drop)
/* Mostly the same logic as #view3d_collection_drop_copy_external_asset(), just different enough to
* make sharing code a bit difficult. */
-static void view3d_ob_drop_copy_external_asset(wmDrag *drag, wmDropBox *drop)
+static void view3d_ob_drop_copy_external_asset(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
/* NOTE(@campbellbarton): Selection is handled here, de-selecting objects before append,
* using auto-select to ensure the new objects are selected.
@@ -771,7 +771,9 @@ static void view3d_ob_drop_copy_external_asset(wmDrag *drag, wmDropBox *drop)
}
}
-static void view3d_collection_drop_copy_local_id(wmDrag *drag, wmDropBox *drop)
+static void view3d_collection_drop_copy_local_id(bContext *UNUSED(C),
+ wmDrag *drag,
+ wmDropBox *drop)
{
ID *id = WM_drag_get_local_ID(drag, ID_GR);
RNA_int_set(drop->ptr, "session_uuid", (int)id->session_uuid);
@@ -779,7 +781,9 @@ static void view3d_collection_drop_copy_local_id(wmDrag *drag, wmDropBox *drop)
/* Mostly the same logic as #view3d_ob_drop_copy_external_asset(), just different enough to make
* sharing code a bit difficult. */
-static void view3d_collection_drop_copy_external_asset(wmDrag *drag, wmDropBox *drop)
+static void view3d_collection_drop_copy_external_asset(bContext *UNUSED(C),
+ wmDrag *drag,
+ wmDropBox *drop)
{
BLI_assert(drag->type == WM_DRAG_ASSET);
@@ -815,14 +819,14 @@ static void view3d_collection_drop_copy_external_asset(wmDrag *drag, wmDropBox *
ED_undo_push(C, "Collection_Drop");
}
-static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop)
+static void view3d_id_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0);
RNA_string_set(drop->ptr, "name", id->name + 2);
}
-static void view3d_id_drop_copy_with_type(wmDrag *drag, wmDropBox *drop)
+static void view3d_id_drop_copy_with_type(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0);
@@ -830,7 +834,7 @@ static void view3d_id_drop_copy_with_type(wmDrag *drag, wmDropBox *drop)
RNA_enum_set(drop->ptr, "type", GS(id->name));
}
-static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop)
+static void view3d_id_path_drop_copy(bContext *UNUSED(C), wmDrag *drag, wmDropBox *drop)
{
ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0);
@@ -878,7 +882,7 @@ static void view3d_dropboxes(void)
WM_drag_free_imported_drag_ID,
NULL);
- drop->draw = WM_drag_draw_item_name_fn;
+ drop->draw_droptip = WM_drag_draw_item_name_fn;
drop->draw_activate = view3d_ob_drop_draw_activate;
drop->draw_deactivate = view3d_ob_drop_draw_deactivate;
@@ -889,7 +893,7 @@ static void view3d_dropboxes(void)
WM_drag_free_imported_drag_ID,
NULL);
- drop->draw = WM_drag_draw_item_name_fn;
+ drop->draw_droptip = WM_drag_draw_item_name_fn;
drop->draw_activate = view3d_ob_drop_draw_activate;
drop->draw_deactivate = view3d_ob_drop_draw_deactivate;
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 68c9a1c23c3..a3df6a44682 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -11,8 +11,6 @@
#include "ED_transform.h"
#include "ED_view3d.h"
-#include "RE_engine.h"
-
#include "DNA_listBase.h"
#include "DNA_object_enums.h"
diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h
index 2b338f6ad08..7080deaec66 100644
--- a/source/blender/editors/transform/transform_convert.h
+++ b/source/blender/editors/transform/transform_convert.h
@@ -8,6 +8,8 @@
#pragma once
+#include "RE_engine.h"
+
struct BMEditMesh;
struct BMesh;
struct BezTriple;
diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c
index d7d85646b08..c1e8dab3b3e 100644
--- a/source/blender/editors/transform/transform_convert_sequencer.c
+++ b/source/blender/editors/transform/transform_convert_sequencer.c
@@ -326,13 +326,14 @@ static SeqCollection *query_right_side_strips(ListBase *seqbase, SeqCollection *
return collection;
}
-static void seq_transform_update_effects(TransInfo *t, SeqCollection *collection)
+static void seq_transform_update_effects(Scene *scene,
+ ListBase *seqbasep,
+ SeqCollection *collection)
{
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, collection) {
if ((seq->type & SEQ_TYPE_EFFECT) && (seq->seq1 || seq->seq2 || seq->seq3)) {
- ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(t->scene));
- SEQ_time_update_sequence(t->scene, seqbase, seq);
+ SEQ_time_update_sequence(scene, seqbasep, seq);
}
}
}
@@ -357,12 +358,12 @@ static ListBase *seqbase_active_get(const TransInfo *t)
/* Offset all strips positioned after left edge of transformed strips bound-box by amount equal
* to overlap of transformed strips. */
-static void seq_transform_handle_expand_to_fit(TransInfo *t, SeqCollection *transformed_strips)
+static void seq_transform_handle_expand_to_fit(Scene *scene,
+ ListBase *seqbasep,
+ SeqCollection *transformed_strips,
+ bool use_sync_markers)
{
- ListBase *seqbasep = seqbase_active_get(t);
- ListBase *markers = &t->scene->markers;
- const bool use_sync_markers = (((SpaceSeq *)t->area->spacedata.first)->flag &
- SEQ_MARKER_TRANS) != 0;
+ ListBase *markers = &scene->markers;
SeqCollection *right_side_strips = query_right_side_strips(seqbasep, transformed_strips);
@@ -376,7 +377,7 @@ static void seq_transform_handle_expand_to_fit(TransInfo *t, SeqCollection *tran
* strips on left side. */
SeqCollection *standalone_strips = extract_standalone_strips(transformed_strips);
SEQ_transform_seqbase_shuffle_time(
- standalone_strips, seqbasep, t->scene, markers, use_sync_markers);
+ standalone_strips, seqbasep, scene, markers, use_sync_markers);
SEQ_collection_free(standalone_strips);
/* Move temporarily moved strips back to their original place and tag for shuffling. */
@@ -384,17 +385,17 @@ static void seq_transform_handle_expand_to_fit(TransInfo *t, SeqCollection *tran
seq->machine -= MAXSEQ * 2;
}
/* Shuffle again to displace strips on right side. Final effect shuffling is done in
- * seq_transform_handle_overlap. */
+ * SEQ_transform_handle_overlap. */
SEQ_transform_seqbase_shuffle_time(
- right_side_strips, seqbasep, t->scene, markers, use_sync_markers);
- seq_transform_update_effects(t, right_side_strips);
+ right_side_strips, seqbasep, scene, markers, use_sync_markers);
+ seq_transform_update_effects(scene, seqbasep, right_side_strips);
SEQ_collection_free(right_side_strips);
}
-static SeqCollection *query_overwrite_targets(const TransInfo *t,
+static SeqCollection *query_overwrite_targets(ListBase *seqbasep,
SeqCollection *transformed_strips)
{
- SeqCollection *collection = SEQ_query_unselected_strips(seqbase_active_get(t));
+ SeqCollection *collection = SEQ_query_unselected_strips(seqbasep);
Sequence *seq, *seq_transformed;
SEQ_ITERATOR_FOREACH (seq, collection) {
@@ -449,35 +450,36 @@ static eOvelapDescrition overlap_description_get(const Sequence *transformed,
}
/* Split strip in 3 parts, remove middle part and fit transformed inside. */
-static void seq_transform_handle_overwrite_split(const TransInfo *t,
+static void seq_transform_handle_overwrite_split(Scene *scene,
+ ListBase *seqbasep,
const Sequence *transformed,
Sequence *target)
{
- Main *bmain = CTX_data_main(t->context);
- Scene *scene = t->scene;
- ListBase *seqbase = seqbase_active_get(t);
+ /* Because we are doing a soft split, bmain is not used in SEQ_edit_strip_split, so we can pass
+ * NULL here. */
+ Main *bmain = NULL;
Sequence *split_strip = SEQ_edit_strip_split(
- bmain, scene, seqbase, target, transformed->startdisp, SEQ_SPLIT_SOFT, NULL);
+ bmain, scene, seqbasep, target, transformed->startdisp, SEQ_SPLIT_SOFT, NULL);
SEQ_edit_strip_split(
- bmain, scene, seqbase, split_strip, transformed->enddisp, SEQ_SPLIT_SOFT, NULL);
- SEQ_edit_flag_for_removal(scene, seqbase_active_get(t), split_strip);
- SEQ_edit_remove_flagged_sequences(t->scene, seqbase_active_get(t));
+ bmain, scene, seqbasep, split_strip, transformed->enddisp, SEQ_SPLIT_SOFT, NULL);
+ SEQ_edit_flag_for_removal(scene, seqbasep, split_strip);
+ SEQ_edit_remove_flagged_sequences(scene, seqbasep);
}
/* Trim strips by adjusting handle position.
* This is bit more complicated in case overlap happens on effect. */
-static void seq_transform_handle_overwrite_trim(const TransInfo *t,
+static void seq_transform_handle_overwrite_trim(Scene *scene,
+ ListBase *seqbasep,
const Sequence *transformed,
Sequence *target,
const eOvelapDescrition overlap)
{
- SeqCollection *targets = SEQ_query_by_reference(
- target, seqbase_active_get(t), SEQ_query_strip_effect_chain);
+ SeqCollection *targets = SEQ_query_by_reference(target, seqbasep, SEQ_query_strip_effect_chain);
/* Expand collection by adding all target's children, effects and their children. */
if ((target->type & SEQ_TYPE_EFFECT) != 0) {
- SEQ_collection_expand(seqbase_active_get(t), targets, SEQ_query_strip_effect_chain);
+ SEQ_collection_expand(seqbasep, targets, SEQ_query_strip_effect_chain);
}
/* Trim all non effects, that have influence on effect length which is overlapping. */
@@ -494,15 +496,16 @@ static void seq_transform_handle_overwrite_trim(const TransInfo *t,
SEQ_transform_set_right_handle_frame(seq, transformed->startdisp);
}
- ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(t->scene));
- SEQ_time_update_sequence(t->scene, seqbase, seq);
+ SEQ_time_update_sequence(scene, seqbasep, seq);
}
SEQ_collection_free(targets);
}
-static void seq_transform_handle_overwrite(const TransInfo *t, SeqCollection *transformed_strips)
+static void seq_transform_handle_overwrite(Scene *scene,
+ ListBase *seqbasep,
+ SeqCollection *transformed_strips)
{
- SeqCollection *targets = query_overwrite_targets(t, transformed_strips);
+ SeqCollection *targets = query_overwrite_targets(seqbasep, transformed_strips);
SeqCollection *strips_to_delete = SEQ_collection_create(__func__);
Sequence *target;
@@ -519,10 +522,10 @@ static void seq_transform_handle_overwrite(const TransInfo *t, SeqCollection *tr
SEQ_collection_append_strip(target, strips_to_delete);
}
else if (overlap == STRIP_OVERLAP_IS_INSIDE) {
- seq_transform_handle_overwrite_split(t, transformed, target);
+ seq_transform_handle_overwrite_split(scene, seqbasep, transformed, target);
}
else if (ELEM(overlap, STRIP_OVERLAP_LEFT_SIDE, STRIP_OVERLAP_RIGHT_SIDE)) {
- seq_transform_handle_overwrite_trim(t, transformed, target, overlap);
+ seq_transform_handle_overwrite_trim(scene, seqbasep, transformed, target, overlap);
}
}
}
@@ -534,47 +537,49 @@ static void seq_transform_handle_overwrite(const TransInfo *t, SeqCollection *tr
if (SEQ_collection_len(strips_to_delete) > 0) {
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, strips_to_delete) {
- SEQ_edit_flag_for_removal(t->scene, seqbase_active_get(t), seq);
+ SEQ_edit_flag_for_removal(scene, seqbasep, seq);
}
- SEQ_edit_remove_flagged_sequences(t->scene, seqbase_active_get(t));
+ SEQ_edit_remove_flagged_sequences(scene, seqbasep);
}
SEQ_collection_free(strips_to_delete);
}
-static void seq_transform_handle_overlap_shuffle(const TransInfo *t,
- SeqCollection *transformed_strips)
+static void seq_transform_handle_overlap_shuffle(Scene *scene,
+ ListBase *seqbasep,
+ SeqCollection *transformed_strips,
+ bool use_sync_markers)
{
- ListBase *seqbase = seqbase_active_get(t);
- ListBase *markers = &t->scene->markers;
- const bool use_sync_markers = (((SpaceSeq *)t->area->spacedata.first)->flag &
- SEQ_MARKER_TRANS) != 0;
+ ListBase *markers = &scene->markers;
+
/* Shuffle non strips with no effects attached. */
SeqCollection *standalone_strips = extract_standalone_strips(transformed_strips);
SEQ_transform_seqbase_shuffle_time(
- standalone_strips, seqbase, t->scene, markers, use_sync_markers);
+ standalone_strips, seqbasep, scene, markers, use_sync_markers);
SEQ_collection_free(standalone_strips);
}
-static void seq_transform_handle_overlap(TransInfo *t, SeqCollection *transformed_strips)
+void SEQ_transform_handle_overlap(Scene *scene,
+ ListBase *seqbasep,
+ SeqCollection *transformed_strips,
+ bool use_sync_markers)
{
- ListBase *seqbasep = seqbase_active_get(t);
- const eSeqOverlapMode overlap_mode = SEQ_tool_settings_overlap_mode_get(t->scene);
+ const eSeqOverlapMode overlap_mode = SEQ_tool_settings_overlap_mode_get(scene);
switch (overlap_mode) {
case SEQ_OVERLAP_EXPAND:
- seq_transform_handle_expand_to_fit(t, transformed_strips);
+ seq_transform_handle_expand_to_fit(scene, seqbasep, transformed_strips, use_sync_markers);
break;
case SEQ_OVERLAP_OVERWRITE:
- seq_transform_handle_overwrite(t, transformed_strips);
+ seq_transform_handle_overwrite(scene, seqbasep, transformed_strips);
break;
case SEQ_OVERLAP_SHUFFLE:
- seq_transform_handle_overlap_shuffle(t, transformed_strips);
+ seq_transform_handle_overlap_shuffle(scene, seqbasep, transformed_strips, use_sync_markers);
break;
}
if (seq_transform_check_strip_effects(transformed_strips)) {
/* Update effect strips based on strips just moved in time. */
- seq_transform_update_effects(t, transformed_strips);
+ seq_transform_update_effects(scene, seqbasep, transformed_strips);
}
/* If any effects still overlap, we need to move them up.
@@ -582,7 +587,7 @@ static void seq_transform_handle_overlap(TransInfo *t, SeqCollection *transforme
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, transformed_strips) {
if (SEQ_transform_test_overlap(seqbasep, seq)) {
- SEQ_transform_seqbase_shuffle(seqbasep, seq, t->scene);
+ SEQ_transform_seqbase_shuffle(seqbasep, seq, scene);
}
seq->flag &= ~SEQ_OVERLAP;
}
@@ -622,11 +627,15 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c
return;
}
+ ListBase *seqbasep = seqbase_active_get(t);
+ Scene *scene = t->scene;
+ const bool use_sync_markers = (((SpaceSeq *)t->area->spacedata.first)->flag &
+ SEQ_MARKER_TRANS) != 0;
if (seq_transform_check_overlap(transformed_strips)) {
- seq_transform_handle_overlap(t, transformed_strips);
+ SEQ_transform_handle_overlap(scene, seqbasep, transformed_strips, use_sync_markers);
}
- seq_transform_update_effects(t, transformed_strips);
+ seq_transform_update_effects(scene, seqbasep, transformed_strips);
SEQ_collection_free(transformed_strips);
SEQ_sort(ed->seqbasep);
diff --git a/source/blender/editors/transform/transform_orientations.h b/source/blender/editors/transform/transform_orientations.h
index 5bca05b0c3a..3ac235517a7 100644
--- a/source/blender/editors/transform/transform_orientations.h
+++ b/source/blender/editors/transform/transform_orientations.h
@@ -7,6 +7,8 @@
#pragma once
+#include "RE_engine.h"
+
struct TransInfo;
/**
diff --git a/source/blender/editors/transform/transform_snap_sequencer.c b/source/blender/editors/transform/transform_snap_sequencer.c
index 7715388bf52..7dc361ff5bb 100644
--- a/source/blender/editors/transform/transform_snap_sequencer.c
+++ b/source/blender/editors/transform/transform_snap_sequencer.c
@@ -15,6 +15,7 @@
#include "BKE_context.h"
#include "ED_screen.h"
+#include "ED_transform.h"
#include "UI_view2d.h"
@@ -33,7 +34,6 @@ typedef struct TransSeqSnapData {
int *target_snap_points;
int source_snap_point_count;
int target_snap_point_count;
- int final_snap_frame;
} TransSeqSnapData;
/* -------------------------------------------------------------------- */
@@ -58,9 +58,7 @@ static int cmp_fn(const void *a, const void *b)
return (*(int *)a - *(int *)b);
}
-static void seq_snap_source_points_build(const TransInfo *UNUSED(t),
- TransSeqSnapData *snap_data,
- SeqCollection *snap_sources)
+static void seq_snap_source_points_build(TransSeqSnapData *snap_data, SeqCollection *snap_sources)
{
int i = 0;
Sequence *seq;
@@ -121,15 +119,17 @@ static SeqCollection *seq_collection_extract_effects(SeqCollection *collection)
return effects;
}
-static SeqCollection *query_snap_targets(const TransInfo *t, SeqCollection *snap_sources)
+static SeqCollection *query_snap_targets(Scene *scene,
+ SeqCollection *snap_sources,
+ bool exclude_selected)
{
- Editing *ed = SEQ_editing_get(t->scene);
+ Editing *ed = SEQ_editing_get(scene);
ListBase *seqbase = SEQ_active_seqbase_get(ed);
ListBase *channels = SEQ_channels_displayed_get(ed);
- const short snap_flag = SEQ_tool_settings_snap_flag_get(t->scene);
+ const short snap_flag = SEQ_tool_settings_snap_flag_get(scene);
SeqCollection *snap_targets = SEQ_collection_create(__func__);
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
- if (seq->flag & SELECT) {
+ if (exclude_selected && seq->flag & SELECT) {
continue; /* Selected are being transformed. */
}
if (SEQ_render_is_muted(channels, seq) && (snap_flag & SEQ_SNAP_IGNORE_MUTED)) {
@@ -152,12 +152,8 @@ static SeqCollection *query_snap_targets(const TransInfo *t, SeqCollection *snap
return snap_targets;
}
-static int seq_get_snap_target_points_count(const TransInfo *t,
- TransSeqSnapData *UNUSED(snap_data),
- SeqCollection *snap_targets)
+static int seq_get_snap_target_points_count(short snap_mode, SeqCollection *snap_targets)
{
- const short snap_mode = t->tsnap.mode;
-
int count = 2; /* Strip start and end are always used. */
if (snap_mode & SEQ_SNAP_TO_STRIP_HOLD) {
@@ -173,23 +169,21 @@ static int seq_get_snap_target_points_count(const TransInfo *t,
return count;
}
-static void seq_snap_target_points_alloc(const TransInfo *t,
+static void seq_snap_target_points_alloc(short snap_mode,
TransSeqSnapData *snap_data,
SeqCollection *snap_targets)
{
- const size_t point_count = seq_get_snap_target_points_count(t, snap_data, snap_targets);
+ const size_t point_count = seq_get_snap_target_points_count(snap_mode, snap_targets);
snap_data->target_snap_points = MEM_callocN(sizeof(int) * point_count, __func__);
memset(snap_data->target_snap_points, 0, sizeof(int));
snap_data->target_snap_point_count = point_count;
}
-static void seq_snap_target_points_build(const TransInfo *t,
+static void seq_snap_target_points_build(Scene *scene,
+ short snap_mode,
TransSeqSnapData *snap_data,
SeqCollection *snap_targets)
{
- const Scene *scene = t->scene;
- const short snap_mode = t->tsnap.mode;
-
int i = 0;
if (snap_mode & SEQ_SNAP_TO_CURRENT_FRAME) {
@@ -246,11 +240,12 @@ TransSeqSnapData *transform_snap_sequencer_data_alloc(const TransInfo *t)
return NULL;
}
+ Scene *scene = t->scene;
TransSeqSnapData *snap_data = MEM_callocN(sizeof(TransSeqSnapData), __func__);
- ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(t->scene));
+ ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(scene));
SeqCollection *snap_sources = SEQ_query_selected_strips(seqbase);
- SeqCollection *snap_targets = query_snap_targets(t, snap_sources);
+ SeqCollection *snap_targets = query_snap_targets(scene, snap_sources, true);
if (SEQ_collection_len(snap_sources) == 0) {
SEQ_collection_free(snap_targets);
@@ -261,11 +256,12 @@ TransSeqSnapData *transform_snap_sequencer_data_alloc(const TransInfo *t)
/* Build arrays of snap points. */
seq_snap_source_points_alloc(snap_data, snap_sources);
- seq_snap_source_points_build(t, snap_data, snap_sources);
+ seq_snap_source_points_build(snap_data, snap_sources);
SEQ_collection_free(snap_sources);
- seq_snap_target_points_alloc(t, snap_data, snap_targets);
- seq_snap_target_points_build(t, snap_data, snap_targets);
+ short snap_mode = t->tsnap.mode;
+ seq_snap_target_points_alloc(snap_mode, snap_data, snap_targets);
+ seq_snap_target_points_build(scene, snap_mode, snap_data, snap_targets);
SEQ_collection_free(snap_targets);
return snap_data;
@@ -321,3 +317,73 @@ void transform_snap_sequencer_apply_translate(TransInfo *t, float *vec)
{
*vec += t->tsnap.snapPoint[0] - t->tsnap.snapTarget[0];
}
+
+static int transform_snap_sequencer_to_closest_strip_ex(TransInfo *t, int frame_1, int frame_2)
+{
+ Scene *scene = t->scene;
+ TransSeqSnapData *snap_data = MEM_callocN(sizeof(TransSeqSnapData), __func__);
+
+ SeqCollection *empty_col = SEQ_collection_create(__func__);
+ SeqCollection *snap_targets = query_snap_targets(scene, empty_col, false);
+ SEQ_collection_free(empty_col);
+
+ snap_data->source_snap_points = MEM_callocN(sizeof(int) * 2, __func__);
+ snap_data->source_snap_point_count = 2;
+ BLI_assert(frame_1 <= frame_2);
+ snap_data->source_snap_points[0] = frame_1;
+ snap_data->source_snap_points[1] = frame_2;
+
+ short snap_mode = t->tsnap.mode;
+ /* Build arrays of snap points. */
+ seq_snap_target_points_alloc(snap_mode, snap_data, snap_targets);
+ seq_snap_target_points_build(scene, snap_mode, snap_data, snap_targets);
+ SEQ_collection_free(snap_targets);
+
+ t->tsnap.seq_context = snap_data;
+ bool snap_success = transform_snap_sequencer_calc(t);
+ transform_snap_sequencer_data_free(snap_data);
+ t->tsnap.seq_context = NULL;
+
+ float snap_offset = 0;
+ if (snap_success) {
+ t->tsnap.status |= (POINT_INIT | TARGET_INIT);
+ transform_snap_sequencer_apply_translate(t, &snap_offset);
+ }
+ else {
+ t->tsnap.status &= ~(POINT_INIT | TARGET_INIT);
+ }
+
+ return snap_offset;
+}
+
+bool ED_transform_snap_sequencer_to_closest_strip_calc(Scene *scene,
+ ARegion *region,
+ int frame_1,
+ int frame_2,
+ int *r_snap_distance,
+ float *r_snap_frame)
+{
+ TransInfo t;
+ t.scene = scene;
+ t.region = region;
+ t.values[0] = 0;
+ t.data_type = TC_SEQ_DATA;
+
+ t.tsnap.mode = SEQ_tool_settings_snap_mode_get(scene);
+ *r_snap_distance = transform_snap_sequencer_to_closest_strip_ex(&t, frame_1, frame_2);
+ *r_snap_frame = t.tsnap.snapPoint[0];
+ return validSnap(&t);
+}
+
+void ED_draw_sequencer_snap_point(struct bContext *C, float snap_point)
+{
+ /* Reuse the snapping drawing code from the transform system. */
+ TransInfo t;
+ t.mode = TFM_SEQ_SLIDE;
+ t.modifiers = MOD_SNAP;
+ t.spacetype = SPACE_SEQ;
+ t.tsnap.status = (POINT_INIT | TARGET_INIT);
+ t.tsnap.snapPoint[0] = snap_point;
+
+ drawSnapping(C, &t);
+}
diff --git a/source/blender/sequencer/SEQ_transform.h b/source/blender/sequencer/SEQ_transform.h
index a342dfe10a2..ea90a3ed372 100644
--- a/source/blender/sequencer/SEQ_transform.h
+++ b/source/blender/sequencer/SEQ_transform.h
@@ -51,6 +51,11 @@ bool SEQ_transform_seqbase_shuffle_time(struct SeqCollection *strips_to_shuffle,
struct Scene *evil_scene,
struct ListBase *markers,
bool use_sync_markers);
+
+void SEQ_transform_handle_overlap(struct Scene *scene,
+ struct ListBase *seqbasep,
+ struct SeqCollection *transformed_strips,
+ bool use_sync_markers);
/**
* Check if the selected seq's reference unselected seq's.
*/
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 1427200b9cd..9a4d024328a 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -1164,7 +1164,7 @@ struct wmDropBox *WM_dropbox_add(
ListBase *lb,
const char *idname,
bool (*poll)(struct bContext *, struct wmDrag *, const struct wmEvent *event),
- void (*copy)(struct wmDrag *, struct wmDropBox *),
+ void (*copy)(struct bContext *, struct wmDrag *, struct wmDropBox *),
void (*cancel)(struct Main *, struct wmDrag *, struct wmDropBox *),
WMDropboxTooltipFunc tooltip);
void WM_drag_draw_item_name_fn(struct bContext *C,
@@ -1294,6 +1294,7 @@ enum {
WM_JOB_TYPE_TRACE_IMAGE,
WM_JOB_TYPE_LINEART,
WM_JOB_TYPE_SEQ_DRAW_THUMBNAIL,
+ WM_JOB_TYPE_SEQ_DRAG_DROP_PREVIEW,
/* add as needed, bake, seq proxy build
* if having hard coded values is a problem */
};
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 11603b9e5f7..a9b8d91ca03 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -1169,8 +1169,13 @@ typedef struct wmDropBox {
/** Test if the dropbox is active. */
bool (*poll)(struct bContext *C, struct wmDrag *drag, const wmEvent *event);
+ /** Called when the drag action starts. Can be used to prefetch data for previews.
+ * \note The dropbox that will be called eventually is not known yet when starting the drag.
+ * So this callback is called on every dropbox that is registered in the current screen. */
+ void (*on_drag_start)(struct bContext *C, struct wmDrag *drag);
+
/** Before exec, this copies drag info to #wmDrop properties. */
- void (*copy)(struct wmDrag *drag, struct wmDropBox *drop);
+ void (*copy)(struct bContext *C, struct wmDrag *drag, struct wmDropBox *drop);
/**
* If the operator is canceled (returns `OPERATOR_CANCELLED`), this can be used for cleanup of
@@ -1179,15 +1184,29 @@ typedef struct wmDropBox {
void (*cancel)(struct Main *bmain, struct wmDrag *drag, struct wmDropBox *drop);
/**
- * Override the default drawing function.
+ * Override the default cursor overlay drawing function.
+ * Can be used to draw text or thumbnails. IE a tooltip for drag and drop.
+ * \param xy: Cursor location in window coordinates (#wmEvent.xy compatible).
+ */
+ void (*draw_droptip)(struct bContext *C,
+ struct wmWindow *win,
+ struct wmDrag *drag,
+ const int xy[2]);
+
+ /** Called with the draw buffer (#GPUViewport) set up for drawing into the region's view.
+ * \note Only setups the drawing buffer for drawing in view, not the GPU transform matricies.
+ * The callback has to do that itself, with for example #UI_view2d_view_ortho.
* \param xy: Cursor location in window coordinates (#wmEvent.xy compatible).
*/
- void (*draw)(struct bContext *C, struct wmWindow *win, struct wmDrag *drag, const int xy[2]);
+ void (*draw_in_view)(struct bContext *C,
+ struct wmWindow *win,
+ struct wmDrag *drag,
+ const int xy[2]);
- /** Called when pool returns true the first time. */
+ /** Called when poll returns true the first time. */
void (*draw_activate)(struct wmDropBox *drop, struct wmDrag *drag);
- /** Called when pool returns false the first time or when the drag event ends. */
+ /** Called when poll returns false the first time or when the drag event ends. */
void (*draw_deactivate)(struct wmDropBox *drop, struct wmDrag *drag);
/** Custom data for drawing. */
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index 4970b09c18b..a98ded82a92 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -17,6 +17,7 @@
#include "BLT_translation.h"
+#include "BLI_bitmap.h"
#include "BLI_blenlib.h"
#include "BLI_math_color.h"
@@ -95,7 +96,7 @@ ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid)
wmDropBox *WM_dropbox_add(ListBase *lb,
const char *idname,
bool (*poll)(bContext *, wmDrag *, const wmEvent *),
- void (*copy)(wmDrag *, wmDropBox *),
+ void (*copy)(bContext *, wmDrag *, wmDropBox *),
void (*cancel)(struct Main *, wmDrag *, wmDropBox *),
WMDropboxTooltipFunc tooltip)
{
@@ -136,6 +137,44 @@ void wm_dropbox_free(void)
/* *********************************** */
+static void wm_dropbox_invoke(bContext *C, wmDrag *drag)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+
+ /* Create a bitmap flag matrix of all currently visible region and area types.
+ * Everything that isn't visible in the current window should not prefetch any data. */
+ bool area_region_tag[SPACE_TYPE_NUM][RGN_TYPE_NUM] = {{false}};
+
+ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
+ bScreen *screen = WM_window_get_active_screen(win);
+ ED_screen_areas_iter (win, screen, area) {
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ if (region->visible) {
+ BLI_assert(area->spacetype < SPACE_TYPE_NUM);
+ BLI_assert(region->regiontype < RGN_TYPE_NUM);
+ area_region_tag[area->spacetype][region->regiontype] = true;
+ }
+ }
+ }
+ }
+
+ LISTBASE_FOREACH (wmDropBoxMap *, dm, &dropboxes) {
+ if (!area_region_tag[dm->spaceid][dm->regionid]) {
+ continue;
+ }
+ LISTBASE_FOREACH (wmDropBox *, drop, &dm->dropboxes) {
+ if (drag->drop_state.ui_context) {
+ CTX_store_set(C, drag->drop_state.ui_context);
+ }
+
+ if (drop->on_drag_start) {
+ drop->on_drag_start(C, drag);
+ }
+ CTX_store_set(C, NULL);
+ }
+ }
+}
+
wmDrag *WM_event_start_drag(
struct bContext *C, int icon, int type, void *poin, double value, unsigned int flags)
{
@@ -187,6 +226,8 @@ wmDrag *WM_event_start_drag(
}
drag->value = value;
+ wm_dropbox_invoke(C, drag);
+
return drag;
}
@@ -416,7 +457,7 @@ void wm_drop_prepare(bContext *C, wmDrag *drag, wmDropBox *drop)
* operator fails anyway, it might do more than just set properties (e.g.
* typically import an asset). */
if (drop->copy && WM_operator_poll_context(C, drop->ot, opcontext)) {
- drop->copy(drag, drop);
+ drop->copy(C, drag, drop);
}
wm_drags_exit(CTX_wm_manager(C), CTX_wm_window(C));
@@ -947,10 +988,16 @@ void wm_drags_draw(bContext *C, wmWindow *win)
CTX_wm_region_set(C, drag->drop_state.region_from);
CTX_store_set(C, drag->drop_state.ui_context);
+ if (region && drag->drop_state.active_dropbox->draw_in_view) {
+ wmViewport(&region->winrct);
+ drag->drop_state.active_dropbox->draw_in_view(C, win, drag, xy);
+ wmWindowViewport(win);
+ }
+
/* Drawing should be allowed to assume the context from handling and polling (that's why we
* restore it above). */
- if (drag->drop_state.active_dropbox->draw) {
- drag->drop_state.active_dropbox->draw(C, win, drag, xy);
+ if (drag->drop_state.active_dropbox->draw_droptip) {
+ drag->drop_state.active_dropbox->draw_droptip(C, win, drag, xy);
continue;
}
}
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 4b506564260..242c96903d3 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -863,6 +863,7 @@ static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view)
/* Needs pixel coords in screen. */
if (wm->drags.first) {
wm_drags_draw(C, win);
+ wmWindowViewport(win);
}
GPU_debug_group_end();