diff --git a/source/blender/blenloader/intern/readfile.cc b/source/blender/blenloader/intern/readfile.cc index 0fd4a6f120a..e6152cf5ee6 100644 --- a/source/blender/blenloader/intern/readfile.cc +++ b/source/blender/blenloader/intern/readfile.cc @@ -99,7 +99,6 @@ #include "BLO_readfile.h" #include "BLO_undofile.hh" -#include "SEQ_clipboard.hh" #include "SEQ_iterator.hh" #include "SEQ_modifier.hh" #include "SEQ_sequencer.hh" diff --git a/source/blender/editors/space_sequencer/CMakeLists.txt b/source/blender/editors/space_sequencer/CMakeLists.txt index 3e4e98c4aec..5e31cd1d0ed 100644 --- a/source/blender/editors/space_sequencer/CMakeLists.txt +++ b/source/blender/editors/space_sequencer/CMakeLists.txt @@ -25,6 +25,7 @@ set(SRC sequencer_buttons.cc sequencer_channels_draw.cc sequencer_channels_edit.cc + sequencer_clipboard.cc sequencer_drag_drop.cc sequencer_edit.cc sequencer_modifier.cc diff --git a/source/blender/editors/space_sequencer/sequencer_clipboard.cc b/source/blender/editors/space_sequencer/sequencer_clipboard.cc new file mode 100644 index 00000000000..1181247a4c8 --- /dev/null +++ b/source/blender/editors/space_sequencer/sequencer_clipboard.cc @@ -0,0 +1,397 @@ +/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved. + * SPDX-FileCopyrightText: 2003-2009 Blender Authors + * SPDX-FileCopyrightText: 2005-2006 Peter Schlaile + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup bke + */ + +#include + +#include "BLO_readfile.h" +#include "MEM_guardedalloc.h" + +#include "ED_keyframing.hh" +#include "ED_outliner.hh" +#include "ED_sequencer.hh" + +#include "DNA_anim_types.h" +#include "DNA_scene_types.h" +#include "DNA_sequence_types.h" +#include "DNA_space_types.h" +#include "DNA_windowmanager_types.h" + +#include "BLI_ghash.h" +#include "BLI_listbase.h" +#include "BLI_path_util.h" + +#include "BKE_appdir.h" +#include "BKE_blender_copybuffer.h" +#include "BKE_blendfile.h" +#include "BKE_context.hh" +#include "BKE_fcurve.h" +#include "BKE_lib_id.h" +#include "BKE_lib_query.h" +#include "BKE_lib_remap.hh" +#include "BKE_main.hh" +#include "BKE_report.h" +#include "BKE_scene.h" + +#include "RNA_access.hh" + +#include "SEQ_animation.hh" +#include "SEQ_select.hh" +#include "SEQ_sequencer.hh" +#include "SEQ_time.hh" +#include "SEQ_transform.hh" +#include "SEQ_utils.hh" + +#include "DEG_depsgraph.hh" +#include "DEG_depsgraph_build.hh" + +#include "WM_api.hh" +#include "WM_types.hh" + +#ifdef WITH_AUDASPACE +# include +#endif + +/* Own include. */ +#include "sequencer_intern.hh" + +/* -------------------------------------------------------------------- */ +/* Copy Operator Helper functions + */ + +static int gather_strip_data_ids_to_null(LibraryIDLinkCallbackData *cb_data) +{ + IDRemapper *id_remapper = static_cast(cb_data->user_data); + ID *id = *cb_data->id_pointer; + + /* We don't care about embedded, loopback, or internal IDs. */ + if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_EMBEDDED_NOT_OWNING)) { + return IDWALK_RET_NOP; + } + if (cb_data->cb_flag & (IDWALK_CB_LOOPBACK | IDWALK_CB_INTERNAL)) { + return IDWALK_RET_STOP_RECURSION; + } + + if (id) { + ID_Type id_type = GS((id)->name); + /* Nullify everything that is not: + * Sound, Movieclip, Image, Text, Vfont, Action, or Collection IDs. + */ + if (!ELEM(id_type, ID_SO, ID_MC, ID_IM, ID_TXT, ID_VF, ID_AC)) { + BKE_id_remapper_add(id_remapper, id, nullptr); + return IDWALK_RET_STOP_RECURSION; + } + } + return IDWALK_RET_NOP; +} + +static void sequencer_copy_animation_listbase(Scene *scene_src, + Sequence *seq_dst, + ListBase *clipboard_dst, + ListBase *fcurve_base_src) +{ + /* Add curves for strips inside meta strip. */ + if (seq_dst->type == SEQ_TYPE_META) { + LISTBASE_FOREACH (Sequence *, meta_child, &seq_dst->seqbase) { + sequencer_copy_animation_listbase(scene_src, meta_child, clipboard_dst, fcurve_base_src); + } + } + + GSet *fcurves_src = SEQ_fcurves_by_strip_get(seq_dst, fcurve_base_src); + if (fcurves_src == nullptr) { + return; + } + + GSET_FOREACH_BEGIN (FCurve *, fcu_src, fcurves_src) { + BLI_addtail(clipboard_dst, BKE_fcurve_copy(fcu_src)); + } + GSET_FOREACH_END(); + + BLI_gset_free(fcurves_src, nullptr); +} + +static void sequencer_copy_animation(Scene *scene_src, + ListBase *fcurves_dst, + ListBase *drivers_dst, + Sequence *seq_dst) +{ + if (SEQ_animation_curves_exist(scene_src)) { + sequencer_copy_animation_listbase( + scene_src, seq_dst, fcurves_dst, &scene_src->adt->action->curves); + } + if (SEQ_animation_drivers_exist(scene_src)) { + sequencer_copy_animation_listbase(scene_src, seq_dst, drivers_dst, &scene_src->adt->drivers); + } +} + +static void sequencer_copybuffer_filepath_get(char filepath[FILE_MAX], size_t filepath_maxncpy) +{ + BLI_path_join(filepath, filepath_maxncpy, BKE_tempdir_base(), "copybuffer_vse.blend"); +} + +static bool sequencer_write_copy_paste_file(Main *bmain_src, + Scene *scene_src, + const char *filepath, + ReportList *reports) + +{ + /* Ideally, scene should not be added to the global Main. There currently is no good + * solution to avoid it if we want to properly pull in all strip dependecies. */ + Scene *scene_dst = BKE_scene_add(bmain_src, "copybuffer_vse_scene"); + + /* Create a temporary scene that we will copy from. + * This is needed as it is the scene that contains all the VSE strip data. + */ + scene_dst->ed = MEM_cnew(__func__); + scene_dst->ed->seqbasep = &scene_dst->ed->seqbase; + SEQ_sequence_base_dupli_recursive( + scene_src, scene_dst, &scene_dst->ed->seqbase, &scene_src->ed->seqbase, 0, 0); + + BLI_duplicatelist(&scene_dst->ed->channels, &scene_src->ed->channels); + scene_dst->ed->displayed_channels = &scene_dst->ed->channels; + + /* Save current frame and active strip. */ + scene_dst->r.cfra = scene_src->r.cfra; + Sequence *active_seq_src = SEQ_select_active_get(scene_src); + if (active_seq_src) { + Sequence *seq_dst = static_cast( + BLI_findstring(&scene_dst->ed->seqbase, active_seq_src->name, offsetof(Sequence, name))); + if (seq_dst) { + SEQ_select_active_set(scene_dst, seq_dst); + } + } + + ListBase fcurves_dst = {nullptr, nullptr}; + ListBase drivers_dst = {nullptr, nullptr}; + LISTBASE_FOREACH (Sequence *, seq_dst, &scene_dst->ed->seqbase) { + /* Copy animation curves from seq_dst (if any). */ + sequencer_copy_animation(scene_src, &fcurves_dst, &drivers_dst, seq_dst); + } + + if (!BLI_listbase_is_empty(&fcurves_dst) || !BLI_listbase_is_empty(&drivers_dst)) { + BLI_assert(scene_dst->adt == nullptr); + bAction *act_dst = ED_id_action_ensure(bmain_src, &scene_dst->id); + BLI_movelisttolist(&act_dst->curves, &fcurves_dst); + BLI_movelisttolist(&scene_dst->adt->drivers, &drivers_dst); + } + + /* Nullify all ID pointers that we don't want to copy. For example, we don't want + * to copy whole scenes. We have to come up with a proper idea of how to copy and + * paste scene strips. + */ + IDRemapper *id_remapper = BKE_id_remapper_create(); + BKE_library_foreach_ID_link( + bmain_src, &scene_dst->id, gather_strip_data_ids_to_null, id_remapper, IDWALK_RECURSE); + + BKE_libblock_remap_multiple(bmain_src, id_remapper, 0); + BKE_id_remapper_free(id_remapper); + + /* Ensure that there are no old copy tags around */ + BKE_blendfile_write_partial_begin(bmain_src); + /* Tag the scene copy so we can pull in all scrip deps */ + BKE_copybuffer_copy_tag_ID(&scene_dst->id); + /* Create the copy/paste temp file */ + bool retval = BKE_copybuffer_copy_end(bmain_src, filepath, reports); + + /* Clean up the action ID if we created any. */ + if (scene_dst->adt != nullptr && scene_dst->adt->action != nullptr) { + BKE_id_delete(bmain_src, scene_dst->adt->action); + } + + /* Cleanup the dummy scene file */ + BKE_id_delete(bmain_src, scene_dst); + + return retval; +} + +int sequencer_clipboard_copy_exec(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + Editing *ed = SEQ_editing_get(scene); + + if (SEQ_transform_seqbase_isolated_sel_check(ed->seqbasep) == false) { + BKE_report(op->reports, RPT_ERROR, "Please select all related strips"); + return OPERATOR_CANCELLED; + } + + char filepath[FILE_MAX]; + sequencer_copybuffer_filepath_get(filepath, sizeof(filepath)); + bool success = sequencer_write_copy_paste_file(bmain, scene, filepath, op->reports); + if (!success) { + BKE_report(op->reports, RPT_ERROR, "Could not create the copy paste file!"); + return OPERATOR_CANCELLED; + } + + /* We are all done! */ + BKE_report(op->reports, RPT_INFO, "Copied the selected VSE strips to internal clipboard"); + return OPERATOR_FINISHED; +} + +/* -------------------------------------------------------------------- */ +/* Paste Operator Helper functions + */ + +static bool sequencer_paste_animation(Main *bmain_dst, Scene *scene_dst, Scene *scene_src) +{ + if (!SEQ_animation_curves_exist(scene_src) && !SEQ_animation_drivers_exist(scene_src)) { + return false; + } + + bAction *act_dst; + + if (scene_dst->adt != nullptr && scene_dst->adt->action != nullptr) { + act_dst = scene_dst->adt->action; + } + else { + /* get action to add F-Curve+keyframe to */ + act_dst = ED_id_action_ensure(bmain_dst, &scene_dst->id); + } + + LISTBASE_FOREACH (FCurve *, fcu, &scene_src->adt->action->curves) { + BLI_addtail(&act_dst->curves, BKE_fcurve_copy(fcu)); + } + LISTBASE_FOREACH (FCurve *, fcu, &scene_src->adt->drivers) { + BLI_addtail(&scene_dst->adt->drivers, BKE_fcurve_copy(fcu)); + } + + return true; +} + +int sequencer_clipboard_paste_exec(bContext *C, wmOperator *op) +{ + char filepath[FILE_MAX]; + sequencer_copybuffer_filepath_get(filepath, sizeof(filepath)); + const BlendFileReadParams params{}; + BlendFileReadReport bf_reports{}; + BlendFileData *bfd = BKE_blendfile_read(filepath, ¶ms, &bf_reports); + + if (bfd == nullptr) { + BKE_report(op->reports, RPT_INFO, "No data to paste"); + return OPERATOR_CANCELLED; + } + + Main *bmain_src = bfd->main; + bfd->main = nullptr; + BLO_blendfiledata_free(bfd); + + Scene *scene_src = nullptr; + /* Find the scene we pasted that contains the strips. It should be tagged. */ + LISTBASE_FOREACH (Scene *, scene_iter, &bmain_src->scenes) { + if (scene_iter->id.flag & LIB_CLIPBOARD_MARK) { + scene_src = scene_iter; + break; + } + } + + if (!scene_src || !scene_src->ed) { + BKE_report(op->reports, RPT_ERROR, "No clipboard scene to paste VSE data from"); + BKE_main_free(bmain_src); + return OPERATOR_CANCELLED; + } + + const int num_strips_to_paste = BLI_listbase_count(&scene_src->ed->seqbase); + if (num_strips_to_paste == 0) { + BKE_report(op->reports, RPT_INFO, "No strips to paste"); + BKE_main_free(bmain_src); + return OPERATOR_CANCELLED; + } + + Scene *scene_dst = CTX_data_scene(C); + Editing *ed_dst = SEQ_editing_ensure(scene_dst); /* Creates "ed" if it's missing. */ + int ofs; + + ED_sequencer_deselect_all(scene_dst); + if (RNA_boolean_get(op->ptr, "keep_offset")) { + ofs = scene_dst->r.cfra - scene_src->r.cfra; + } + else { + int min_seq_startdisp = INT_MAX; + LISTBASE_FOREACH (Sequence *, seq, &scene_src->ed->seqbase) { + if (SEQ_time_left_handle_frame_get(scene_src, seq) < min_seq_startdisp) { + min_seq_startdisp = SEQ_time_left_handle_frame_get(scene_src, seq); + } + } + /* Paste strips relative to the current-frame. */ + ofs = scene_dst->r.cfra - min_seq_startdisp; + } + + Sequence *prev_active_seq = SEQ_select_active_get(scene_src); + std::string active_seq_name; + if (prev_active_seq) { + active_seq_name.assign(prev_active_seq->name); + } + + /* Make sure we have all data IDs we need in bmain_dst. Remap the IDs if we already have them. + * This has to happen BEFORE we move the strip over to scene_dst. their ID mapping will not be + * correct otherwise. */ + Main *bmain_dst = CTX_data_main(C); + MainMergeReport merge_reports = {}; + /* NOTE: BKE_main_merge will free bmain_src! */ + BKE_main_merge(bmain_dst, &bmain_src, merge_reports); + + /* Paste animation. + * NOTE: Only fcurves and drivers are copied. NLA action strips are not copied. + * First backup original curves from scene and move curves from clipboard into scene. This way, + * when pasted strips are renamed, pasted fcurves are renamed with them. Finally restore original + * curves from backup. + */ + SeqAnimationBackup animation_backup = {{nullptr}}; + SEQ_animation_backup_original(scene_dst, &animation_backup); + bool has_animation = sequencer_paste_animation(bmain_dst, scene_dst, scene_src); + + ListBase nseqbase = {nullptr, nullptr}; + /* NOTE: SEQ_sequence_base_dupli_recursive() takes care of generating + * new UUIDs for sequences in the new list. */ + SEQ_sequence_base_dupli_recursive( + scene_src, scene_dst, &nseqbase, &scene_src->ed->seqbase, 0, 0); + + /* BKE_main_merge will copy the scene_src and its action into bmain_dst. Remove them as + * we merge the data from these manually. + */ + if (has_animation) { + BKE_id_delete(bmain_dst, scene_src->adt->action); + } + BKE_id_delete(bmain_dst, scene_src); + + Sequence *iseq_first = static_cast(nseqbase.first); + BLI_movelisttolist(ed_dst->seqbasep, &nseqbase); + /* Restore "first" pointer as BLI_movelisttolist sets it to nullptr */ + nseqbase.first = iseq_first; + + LISTBASE_FOREACH (Sequence *, iseq, &nseqbase) { + if (STREQ(iseq->name, active_seq_name.c_str())) { + SEQ_select_active_set(scene_dst, iseq); + } + /* 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(iseq, scene_dst); + } + + LISTBASE_FOREACH (Sequence *, iseq, &nseqbase) { + /* Translate after name has been changed, otherwise this will affect animdata of original + * strip. */ + SEQ_transform_translate_sequence(scene_dst, iseq, ofs); + /* Ensure, that pasted strips don't overlap. */ + if (SEQ_transform_test_overlap(scene_dst, ed_dst->seqbasep, iseq)) { + SEQ_transform_seqbase_shuffle(ed_dst->seqbasep, iseq, scene_dst); + } + } + + SEQ_animation_restore_original(scene_dst, &animation_backup); + + DEG_id_tag_update(&scene_dst->id, ID_RECALC_SEQUENCER_STRIPS); + DEG_relations_tag_update(bmain_dst); + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene_dst); + ED_outliner_select_sync_from_sequence_tag(C); + + BKE_reportf(op->reports, RPT_INFO, "%d strips pasted", num_strips_to_paste); + + return OPERATOR_FINISHED; +} diff --git a/source/blender/editors/space_sequencer/sequencer_edit.cc b/source/blender/editors/space_sequencer/sequencer_edit.cc index 2bd8463d181..b6ead44d314 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.cc +++ b/source/blender/editors/space_sequencer/sequencer_edit.cc @@ -6,15 +6,11 @@ * \ingroup spseq */ -#include -#include -#include - #include "MEM_guardedalloc.h" -#include "BLI_blenlib.h" -#include "BLI_ghash.h" +#include "BLI_fileops.h" #include "BLI_math_vector.h" +#include "BLI_path_util.h" #include "BLI_string.h" #include "BLI_timecode.h" #include "BLI_utildefines.h" @@ -28,7 +24,6 @@ #include "BKE_context.hh" #include "BKE_fcurve.h" #include "BKE_global.h" -#include "BKE_lib_id.h" #include "BKE_main.hh" #include "BKE_report.h" #include "BKE_sound.h" @@ -36,7 +31,6 @@ #include "SEQ_add.hh" #include "SEQ_animation.hh" #include "SEQ_channels.hh" -#include "SEQ_clipboard.hh" #include "SEQ_edit.hh" #include "SEQ_effects.hh" #include "SEQ_iterator.hh" @@ -58,9 +52,7 @@ /* For menu, popup, icons, etc. */ #include "ED_fileselect.hh" -#include "ED_keyframing.hh" #include "ED_numinput.hh" -#include "ED_outliner.hh" #include "ED_scene.hh" #include "ED_screen.hh" #include "ED_sequencer.hh" @@ -2458,94 +2450,6 @@ void SEQUENCER_OT_rendersize(wmOperatorType *ot) /** \name Copy Operator * \{ */ -static void seq_copy_del_sound(Scene *scene, Sequence *seq) -{ - if (seq->type == SEQ_TYPE_META) { - LISTBASE_FOREACH (Sequence *, iseq, &seq->seqbase) { - seq_copy_del_sound(scene, iseq); - } - } - else if (seq->scene_sound) { - BKE_sound_remove_scene_sound(scene, seq->scene_sound); - seq->scene_sound = nullptr; - } -} - -static void sequencer_copy_animation_listbase(Scene *scene, - Sequence *seq, - ListBase *clipboard, - ListBase *fcurve_base) -{ - /* Add curves for strips inside meta strip. */ - if (seq->type == SEQ_TYPE_META) { - LISTBASE_FOREACH (Sequence *, meta_child, &seq->seqbase) { - sequencer_copy_animation_listbase(scene, meta_child, clipboard, fcurve_base); - } - } - - GSet *fcurves = SEQ_fcurves_by_strip_get(seq, fcurve_base); - if (fcurves == nullptr) { - return; - } - - GSET_FOREACH_BEGIN (FCurve *, fcu, fcurves) { - BLI_addtail(clipboard, BKE_fcurve_copy(fcu)); - } - GSET_FOREACH_END(); - - BLI_gset_free(fcurves, nullptr); -} - -static void sequencer_copy_animation(Scene *scene, Sequence *seq) -{ - if (SEQ_animation_curves_exist(scene)) { - sequencer_copy_animation_listbase(scene, seq, &fcurves_clipboard, &scene->adt->action->curves); - } - if (SEQ_animation_drivers_exist(scene)) { - sequencer_copy_animation_listbase(scene, seq, &drivers_clipboard, &scene->adt->drivers); - } -} - -static int sequencer_copy_exec(bContext *C, wmOperator *op) -{ - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - Editing *ed = SEQ_editing_get(scene); - - SEQ_clipboard_free(); - - if (SEQ_transform_seqbase_isolated_sel_check(ed->seqbasep) == false) { - BKE_report(op->reports, RPT_ERROR, "Please select all related strips"); - return OPERATOR_CANCELLED; - } - - /* NOTE: The UUID is re-generated on paste, so we can keep UUID in the clipboard since - * nobody can reach them anyway. - * This reduces chance or running out of UUIDs if a cat falls asleep on Ctrl-C. */ - SEQ_sequence_base_dupli_recursive(scene, - scene, - &seqbase_clipboard, - ed->seqbasep, - 0, - (LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_FREE_NO_MAIN)); - - seqbase_clipboard_frame = scene->r.cfra; - SEQ_clipboard_active_seq_name_store(scene); - - LISTBASE_FOREACH (Sequence *, seq, &seqbase_clipboard) { - /* Copy curves. */ - sequencer_copy_animation(scene, seq); - /* Remove anything that references the current scene. */ - seq_copy_del_sound(scene, seq); - } - - /* Replace datablock pointers with copies, to keep things working in case - * data-blocks get deleted or another .blend file is opened. */ - SEQ_clipboard_pointers_store(bmain, &seqbase_clipboard); - - return OPERATOR_FINISHED; -} - void SEQUENCER_OT_copy(wmOperatorType *ot) { /* Identifiers. */ @@ -2554,7 +2458,7 @@ void SEQUENCER_OT_copy(wmOperatorType *ot) ot->description = "Copy the selected strips to the internal clipboard"; /* Api callbacks. */ - ot->exec = sequencer_copy_exec; + ot->exec = sequencer_clipboard_copy_exec; ot->poll = sequencer_edit_poll; /* Flags. */ @@ -2585,114 +2489,6 @@ bool ED_sequencer_deselect_all(Scene *scene) return changed; } -static void sequencer_paste_animation(bContext *C) -{ - if (BLI_listbase_is_empty(&fcurves_clipboard) && BLI_listbase_is_empty(&drivers_clipboard)) { - return; - } - - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - bAction *act; - - if (scene->adt != nullptr && scene->adt->action != nullptr) { - act = scene->adt->action; - } - else { - /* get action to add F-Curve+keyframe to */ - act = ED_id_action_ensure(bmain, &scene->id); - } - - LISTBASE_FOREACH (FCurve *, fcu, &fcurves_clipboard) { - BLI_addtail(&act->curves, BKE_fcurve_copy(fcu)); - } - LISTBASE_FOREACH (FCurve *, fcu, &drivers_clipboard) { - BLI_addtail(&scene->adt->drivers, BKE_fcurve_copy(fcu)); - } -} - -static int sequencer_paste_exec(bContext *C, wmOperator *op) -{ - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - Editing *ed = SEQ_editing_ensure(scene); /* Create if needed. */ - ListBase nseqbase = {nullptr, nullptr}; - int ofs; - Sequence *iseq, *iseq_first; - - if (BLI_listbase_count(&seqbase_clipboard) == 0) { - BKE_report(op->reports, RPT_INFO, "No strips to paste"); - return OPERATOR_CANCELLED; - } - - ED_sequencer_deselect_all(scene); - if (RNA_boolean_get(op->ptr, "keep_offset")) { - ofs = scene->r.cfra - seqbase_clipboard_frame; - } - else { - int min_seq_startdisp = INT_MAX; - LISTBASE_FOREACH (Sequence *, seq, &seqbase_clipboard) { - 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. */ - ofs = scene->r.cfra - min_seq_startdisp; - } - - /* Paste animation. - * NOTE: Only fcurves are copied. Drivers and NLA action strips are not copied. - * First backup original curves from scene and move curves from clipboard into scene. This way, - * when pasted strips are renamed, pasted fcurves are renamed with them. Finally restore original - * curves from backup. - */ - - SeqAnimationBackup animation_backup = {{nullptr}}; - SEQ_animation_backup_original(scene, &animation_backup); - sequencer_paste_animation(C); - - /* Copy strips, temporarily restoring pointers to actual data-blocks. This - * must happen on the clipboard itself, so that copying does user counting - * on the actual data-blocks. */ - SEQ_clipboard_pointers_restore(&seqbase_clipboard, bmain); - SEQ_sequence_base_dupli_recursive(scene, scene, &nseqbase, &seqbase_clipboard, 0, 0); - SEQ_clipboard_pointers_store(bmain, &seqbase_clipboard); - - iseq_first = static_cast(nseqbase.first); - - /* NOTE: SEQ_sequence_base_dupli_recursive() takes care of generating new UUIDs for sequences - * in the new list. */ - BLI_movelisttolist(ed->seqbasep, &nseqbase); - - for (iseq = iseq_first; iseq; iseq = iseq->next) { - if (SEQ_clipboard_pasted_seq_was_active(iseq)) { - SEQ_select_active_set(scene, iseq); - } - /* 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(iseq, scene); - } - - for (iseq = iseq_first; iseq; iseq = iseq->next) { - /* Translate after name has been changed, otherwise this will affect animdata of original - * strip. */ - SEQ_transform_translate_sequence(scene, iseq, ofs); - /* Ensure, that pasted strips don't overlap. */ - if (SEQ_transform_test_overlap(scene, ed->seqbasep, iseq)) { - SEQ_transform_seqbase_shuffle(ed->seqbasep, iseq, scene); - } - } - - SEQ_animation_restore_original(scene, &animation_backup); - - DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); - DEG_relations_tag_update(bmain); - WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); - ED_outliner_select_sync_from_sequence_tag(C); - - return OPERATOR_FINISHED; -} - void SEQUENCER_OT_paste(wmOperatorType *ot) { /* Identifiers. */ @@ -2701,7 +2497,7 @@ void SEQUENCER_OT_paste(wmOperatorType *ot) ot->description = "Paste strips from the internal clipboard"; /* Api callbacks. */ - ot->exec = sequencer_paste_exec; + ot->exec = sequencer_clipboard_paste_exec; ot->poll = ED_operator_sequencer_active; /* Flags. */ diff --git a/source/blender/editors/space_sequencer/sequencer_intern.hh b/source/blender/editors/space_sequencer/sequencer_intern.hh index 6a8f8b35e88..727dacaa4f0 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.hh +++ b/source/blender/editors/space_sequencer/sequencer_intern.hh @@ -326,3 +326,7 @@ SeqRetimingKey *retiming_mousover_key_get(const bContext *C, const int mval[2], int left_fake_key_frame_get(const bContext *C, const Sequence *seq); int right_fake_key_frame_get(const bContext *C, const Sequence *seq); bool retiming_keys_are_visible(const bContext *C); + +/* `sequencer_clipboard.cc` */ +int sequencer_clipboard_copy_exec(bContext *C, wmOperator *op); +int sequencer_clipboard_paste_exec(bContext *C, wmOperator *op); diff --git a/source/blender/sequencer/CMakeLists.txt b/source/blender/sequencer/CMakeLists.txt index 3737b32e623..4aa9f363653 100644 --- a/source/blender/sequencer/CMakeLists.txt +++ b/source/blender/sequencer/CMakeLists.txt @@ -24,7 +24,6 @@ set(SRC SEQ_add.hh SEQ_animation.hh SEQ_channels.hh - SEQ_clipboard.hh SEQ_edit.hh SEQ_effects.hh SEQ_iterator.hh @@ -43,7 +42,6 @@ set(SRC intern/animation.cc intern/channels.cc - intern/clipboard.cc intern/disk_cache.cc intern/disk_cache.hh intern/effects.cc diff --git a/source/blender/sequencer/SEQ_clipboard.hh b/source/blender/sequencer/SEQ_clipboard.hh deleted file mode 100644 index c0cffd625d8..00000000000 --- a/source/blender/sequencer/SEQ_clipboard.hh +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-FileCopyrightText: 2004 Blender Authors - * - * SPDX-License-Identifier: GPL-2.0-or-later */ - -#pragma once - -/** \file - * \ingroup sequencer - */ - -struct ListBase; -struct Main; -struct Scene; -struct Sequence; - -extern ListBase seqbase_clipboard; -extern ListBase fcurves_clipboard; -extern ListBase drivers_clipboard; -extern int seqbase_clipboard_frame; -void SEQ_clipboard_pointers_store(Main *bmain, ListBase *seqbase); -void SEQ_clipboard_pointers_restore(ListBase *seqbase, Main *bmain); -void SEQ_clipboard_free(); -void SEQ_clipboard_active_seq_name_store(Scene *scene); -/** - * Check if strip was active when it was copied. User should restrict this check to pasted strips - * before ensuring original name, because strip name comparison is used to check. - * - * \param pasted_seq: Strip that is pasted(duplicated) from clipboard - * \return true if strip was active, false otherwise - */ -bool SEQ_clipboard_pasted_seq_was_active(Sequence *pasted_seq); diff --git a/source/blender/sequencer/intern/clipboard.cc b/source/blender/sequencer/intern/clipboard.cc deleted file mode 100644 index af2a957870c..00000000000 --- a/source/blender/sequencer/intern/clipboard.cc +++ /dev/null @@ -1,192 +0,0 @@ -/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved. - * SPDX-FileCopyrightText: 2003-2009 Blender Authors - * SPDX-FileCopyrightText: 2005-2006 Peter Schlaile - * - * SPDX-License-Identifier: GPL-2.0-or-later */ - -/** \file - * \ingroup bke - */ - -#include - -#include "MEM_guardedalloc.h" - -#include "DNA_anim_types.h" -#include "DNA_scene_types.h" -#include "DNA_sequence_types.h" -#include "DNA_sound_types.h" - -#include "BLI_listbase.h" -#include "BLI_string.h" - -#include "BKE_fcurve.h" -#include "BKE_main.hh" -#include "BKE_movieclip.h" -#include "BKE_scene.h" -#include "BKE_sound.h" - -#include "SEQ_clipboard.hh" -#include "SEQ_select.hh" - -#include "sequencer.hh" - -#ifdef WITH_AUDASPACE -# include -#endif - -/* -------------------------------------------------------------------- */ -/* Manage pointers in the clipboard. - * note that these pointers should _never_ be access in the sequencer, - * they are only for storage while in the clipboard - * notice 'newid' is used for temp pointer storage here, validate on access (this is safe usage, - * since those data-blocks are fully out of Main lists). - */ - -ListBase seqbase_clipboard; -ListBase fcurves_clipboard; -ListBase drivers_clipboard; -int seqbase_clipboard_frame; -static char seq_clipboard_active_seq_name[SEQ_NAME_MAXSTR]; - -void seq_clipboard_pointers_free(ListBase *seqbase); - -void SEQ_clipboard_free() -{ - seq_clipboard_pointers_free(&seqbase_clipboard); - - LISTBASE_FOREACH_MUTABLE (Sequence *, seq, &seqbase_clipboard) { - seq_free_sequence_recurse(nullptr, seq, false); - } - BLI_listbase_clear(&seqbase_clipboard); - - LISTBASE_FOREACH_MUTABLE (FCurve *, fcu, &fcurves_clipboard) { - BKE_fcurve_free(fcu); - } - BLI_listbase_clear(&fcurves_clipboard); - - LISTBASE_FOREACH_MUTABLE (FCurve *, fcu, &drivers_clipboard) { - BKE_fcurve_free(fcu); - } - BLI_listbase_clear(&drivers_clipboard); -} - -#define ID_PT (*id_pt) -static void seqclipboard_ptr_free(Main * /*bmain*/, ID **id_pt) -{ - if (ID_PT) { - BLI_assert(ID_PT->newid != nullptr); - MEM_freeN(ID_PT); - ID_PT = nullptr; - } -} -static void seqclipboard_ptr_store(Main * /*bmain*/, ID **id_pt) -{ - if (ID_PT) { - ID *id_prev = ID_PT; - ID_PT = static_cast(MEM_dupallocN(ID_PT)); - ID_PT->newid = id_prev; - } -} -static void seqclipboard_ptr_restore(Main *bmain, ID **id_pt) -{ - if (ID_PT) { - const ListBase *lb = which_libbase(bmain, GS(ID_PT->name)); - void *id_restore; - - BLI_assert(ID_PT->newid != nullptr); - if (BLI_findindex(lb, (ID_PT)->newid) != -1) { - /* the pointer is still valid */ - id_restore = (ID_PT)->newid; - } - else { - /* The pointer of the same name still exists. */ - id_restore = BLI_findstring(lb, (ID_PT)->name + 2, offsetof(ID, name) + 2); - } - - if (id_restore == nullptr) { - /* check for a data with the same filename */ - switch (GS(ID_PT->name)) { - case ID_SO: { - id_restore = BLI_findstring(lb, ((bSound *)ID_PT)->filepath, offsetof(bSound, filepath)); - if (id_restore == nullptr) { - id_restore = BKE_sound_new_file(bmain, ((bSound *)ID_PT)->filepath); - (ID_PT)->newid = static_cast(id_restore); /* reuse next time */ - } - break; - } - case ID_MC: { - id_restore = BLI_findstring( - lb, ((MovieClip *)ID_PT)->filepath, offsetof(MovieClip, filepath)); - if (id_restore == nullptr) { - id_restore = BKE_movieclip_file_add(bmain, ((MovieClip *)ID_PT)->filepath); - (ID_PT)->newid = static_cast(id_restore); /* reuse next time */ - } - break; - } - default: - break; - } - } - - /* Replace with pointer to actual data-block. */ - seqclipboard_ptr_free(bmain, id_pt); - ID_PT = static_cast(id_restore); - } -} -#undef ID_PT - -static void sequence_clipboard_pointers(Main *bmain, - Sequence *seq, - void (*callback)(Main *, ID **)) -{ - callback(bmain, (ID **)&seq->scene); - callback(bmain, (ID **)&seq->scene_camera); - callback(bmain, (ID **)&seq->clip); - callback(bmain, (ID **)&seq->mask); - callback(bmain, (ID **)&seq->sound); - - if (seq->type == SEQ_TYPE_TEXT && seq->effectdata) { - TextVars *text_data = static_cast(seq->effectdata); - callback(bmain, (ID **)&text_data->text_font); - } -} - -/* recursive versions of functions above */ -void seq_clipboard_pointers_free(ListBase *seqbase) -{ - LISTBASE_FOREACH (Sequence *, seq, seqbase) { - sequence_clipboard_pointers(nullptr, seq, seqclipboard_ptr_free); - seq_clipboard_pointers_free(&seq->seqbase); - } -} -void SEQ_clipboard_pointers_store(Main *bmain, ListBase *seqbase) -{ - LISTBASE_FOREACH (Sequence *, seq, seqbase) { - sequence_clipboard_pointers(bmain, seq, seqclipboard_ptr_store); - SEQ_clipboard_pointers_store(bmain, &seq->seqbase); - } -} -void SEQ_clipboard_pointers_restore(ListBase *seqbase, Main *bmain) -{ - LISTBASE_FOREACH (Sequence *, seq, seqbase) { - sequence_clipboard_pointers(bmain, seq, seqclipboard_ptr_restore); - SEQ_clipboard_pointers_restore(&seq->seqbase, bmain); - } -} - -void SEQ_clipboard_active_seq_name_store(Scene *scene) -{ - Sequence *active_seq = SEQ_select_active_get(scene); - if (active_seq != nullptr) { - STRNCPY(seq_clipboard_active_seq_name, active_seq->name); - } - else { - seq_clipboard_active_seq_name[0] = '\0'; - } -} - -bool SEQ_clipboard_pasted_seq_was_active(Sequence *pasted_seq) -{ - return STREQ(pasted_seq->name, seq_clipboard_active_seq_name); -} diff --git a/source/blender/windowmanager/intern/wm_init_exit.cc b/source/blender/windowmanager/intern/wm_init_exit.cc index d081278aec2..41455d75098 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.cc +++ b/source/blender/windowmanager/intern/wm_init_exit.cc @@ -63,8 +63,6 @@ #include "RE_engine.h" #include "RE_pipeline.h" /* RE_ free stuff */ -#include "SEQ_clipboard.hh" /* free seq clipboard */ - #include "IMB_thumbs.h" #ifdef WITH_PYTHON @@ -581,7 +579,6 @@ void WM_exit_ex(bContext *C, const bool do_python_exit, const bool do_user_exit_ ED_preview_restart_queue_free(); ED_assetlist_storage_exit(); - SEQ_clipboard_free(); /* `sequencer.cc` */ BKE_tracking_clipboard_free(); BKE_mask_clipboard_free(); BKE_vfont_clipboard_free();