From 7755411c9033225c3d10cc7d22ebfd5b06e84550 Mon Sep 17 00:00:00 2001 From: Ramon Klauck Date: Fri, 5 Sep 2025 14:32:36 +0200 Subject: [PATCH] VSE: paste strips at mouse in preview This PR makes it possible to paste strips directly at the mouse in the VSE Preview, making it faster to paste strips directly at the position the user wants the strip to be. It is still possible to paste the strip at the original position with the `ctrl + shift + v` shortcut. Pull Request: https://projects.blender.org/blender/blender/pulls/145008 --- .../space_sequencer/sequencer_clipboard.cc | 36 ++++++++++++++++++- .../editors/space_sequencer/sequencer_edit.cc | 5 +++ .../space_sequencer/sequencer_intern.hh | 3 ++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_sequencer/sequencer_clipboard.cc b/source/blender/editors/space_sequencer/sequencer_clipboard.cc index ad1a451b89b..c9d41b575d5 100644 --- a/source/blender/editors/space_sequencer/sequencer_clipboard.cc +++ b/source/blender/editors/space_sequencer/sequencer_clipboard.cc @@ -11,6 +11,7 @@ #include #include +#include "BLI_math_vector_types.hh" #include "BLO_readfile.hh" #include "BLO_writefile.hh" #include "MEM_guardedalloc.h" @@ -42,6 +43,7 @@ #include "SEQ_animation.hh" #include "SEQ_iterator.hh" +#include "SEQ_relations.hh" #include "SEQ_select.hh" #include "SEQ_sequencer.hh" #include "SEQ_time.hh" @@ -55,6 +57,7 @@ #include "ANIM_action_legacy.hh" #include "ANIM_animdata.hh" +#include "UI_view2d.hh" #include "WM_api.hh" #include "WM_types.hh" @@ -396,6 +399,15 @@ static bool sequencer_paste_animation(Main *bmain_dst, Scene *scene_dst, Scene * return true; } +wmOperatorStatus sequencer_clipboard_paste_invoke(bContext *C, + wmOperator *op, + const wmEvent *event) +{ + RNA_int_set(op->ptr, "x", event->mval[0]); + RNA_int_set(op->ptr, "y", event->mval[1]); + return sequencer_clipboard_paste_exec(C, op); +} + wmOperatorStatus sequencer_clipboard_paste_exec(bContext *C, wmOperator *op) { char filepath[FILE_MAX]; @@ -403,6 +415,14 @@ wmOperatorStatus sequencer_clipboard_paste_exec(bContext *C, wmOperator *op) const BlendFileReadParams params{}; BlendFileReadReport bf_reports{}; BlendFileData *bfd = BKE_blendfile_read(filepath, ¶ms, &bf_reports); + const int mval[2] = {RNA_int_get(op->ptr, "x"), RNA_int_get(op->ptr, "y")}; + float2 view_mval; + View2D *v2d = UI_view2d_fromcontext(C); + Scene *scene = CTX_data_sequencer_scene(C); + UI_view2d_region_to_view(v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]); + + /* For checking if region type is Preview. */ + ARegion *region = CTX_wm_region(C); if (bfd == nullptr) { BKE_report(op->reports, RPT_INFO, "No data to paste"); @@ -440,7 +460,7 @@ wmOperatorStatus sequencer_clipboard_paste_exec(bContext *C, wmOperator *op) int ofs; deselect_all_strips(scene_dst); - if (RNA_boolean_get(op->ptr, "keep_offset")) { + if (RNA_boolean_get(op->ptr, "keep_offset") || (region->regiontype == RGN_TYPE_PREVIEW)) { ofs = scene_dst->r.cfra - scene_src->r.cfra; } else { @@ -501,6 +521,7 @@ wmOperatorStatus sequencer_clipboard_paste_exec(bContext *C, wmOperator *op) /* Restore "first" pointer as BLI_movelisttolist sets it to nullptr */ nseqbase.first = iseq_first; + int2 strip_mean_pos = {0, 0}; LISTBASE_FOREACH (Strip *, istrip, &nseqbase) { if (istrip->name == active_seq_name) { seq::select_active_set(scene_dst, istrip); @@ -508,8 +529,13 @@ wmOperatorStatus sequencer_clipboard_paste_exec(bContext *C, wmOperator *op) /* Make sure, that pasted strips have unique names. This has to be done after * adding strips to seqbase, for lookup cache to work correctly. */ seq::ensure_unique_name(istrip, scene_dst); + + strip_mean_pos += static_cast( + seq::image_transform_origin_offset_pixelspace_get(scene, istrip)); } + strip_mean_pos /= BLI_listbase_count(&nseqbase); + LISTBASE_FOREACH (Strip *, istrip, &nseqbase) { /* Translate after name has been changed, otherwise this will affect animdata of original * strip. */ @@ -518,6 +544,14 @@ wmOperatorStatus sequencer_clipboard_paste_exec(bContext *C, wmOperator *op) if (seq::transform_test_overlap(scene_dst, ed_dst->current_strips(), istrip)) { seq::transform_seqbase_shuffle(ed_dst->current_strips(), istrip, scene_dst); } + if (region->regiontype == RGN_TYPE_PREVIEW && !(RNA_boolean_get(op->ptr, "keep_offset"))) { + StripTransform *transform = istrip->data->transform; + const float2 mirror = seq::image_transform_mirror_factor_get(istrip); + const float2 origin = seq::image_transform_origin_offset_pixelspace_get(scene, istrip); + transform->xofs = (view_mval[0] - (strip_mean_pos[0] - origin[0])) * mirror[0]; + transform->yofs = (view_mval[1] - (strip_mean_pos[1] - origin[1])) * mirror[1]; + seq::relations_invalidate_cache(scene, istrip); + } } seq::animation_restore_original(scene_dst, &animation_backup); diff --git a/source/blender/editors/space_sequencer/sequencer_edit.cc b/source/blender/editors/space_sequencer/sequencer_edit.cc index 9d7d6e84638..5b6c3a6d351 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.cc +++ b/source/blender/editors/space_sequencer/sequencer_edit.cc @@ -2860,6 +2860,7 @@ void SEQUENCER_OT_paste(wmOperatorType *ot) ot->description = "Paste strips from the internal clipboard"; /* API callbacks. */ + ot->invoke = sequencer_clipboard_paste_invoke; ot->exec = sequencer_clipboard_paste_exec; ot->poll = ED_operator_sequencer_active; @@ -2874,6 +2875,10 @@ void SEQUENCER_OT_paste(wmOperatorType *ot) "Keep Offset", "Keep strip offset relative to the current frame when pasting"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } /** \} */ diff --git a/source/blender/editors/space_sequencer/sequencer_intern.hh b/source/blender/editors/space_sequencer/sequencer_intern.hh index c34480da10d..0333b5ca664 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.hh +++ b/source/blender/editors/space_sequencer/sequencer_intern.hh @@ -406,6 +406,9 @@ blender::Vector sequencer_visible_strips_get(const Scene *scene, const /* `sequencer_clipboard.cc` */ wmOperatorStatus sequencer_clipboard_copy_exec(bContext *C, wmOperator *op); wmOperatorStatus sequencer_clipboard_paste_exec(bContext *C, wmOperator *op); +wmOperatorStatus sequencer_clipboard_paste_invoke(bContext *C, + wmOperator *op, + const wmEvent *event); /* `sequencer_add_menu_scene_assets.cc` */ MenuType add_catalog_assets_menu_type();