Blender V5.0
sequencer_clipboard.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 * SPDX-FileCopyrightText: 2003-2009 Blender Authors
3 * SPDX-FileCopyrightText: 2005-2006 Peter Schlaile <peter [at] schlaile [dot] de>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later */
6
10
11#include <algorithm>
12#include <cstring>
13#include <limits>
14
16#include "BLO_readfile.hh"
17#include "BLO_writefile.hh"
18#include "MEM_guardedalloc.h"
19
20#include "ED_outliner.hh"
21#include "ED_sequencer.hh"
22
23#include "DNA_anim_types.h"
24#include "DNA_scene_types.h"
25#include "DNA_sequence_types.h"
26#include "DNA_space_types.h"
28
29#include "BLI_listbase.h"
30#include "BLI_path_utils.hh"
31
32#include "BKE_anim_data.hh"
33#include "BKE_appdir.hh"
35#include "BKE_blendfile.hh"
36#include "BKE_context.hh"
37#include "BKE_fcurve.hh"
38#include "BKE_lib_id.hh"
39#include "BKE_lib_query.hh"
40#include "BKE_lib_remap.hh"
41#include "BKE_main.hh"
42#include "BKE_report.hh"
43#include "BKE_scene.hh"
44
45#include "SEQ_animation.hh"
46#include "SEQ_iterator.hh"
47#include "SEQ_relations.hh"
48#include "SEQ_select.hh"
49#include "SEQ_sequencer.hh"
50#include "SEQ_time.hh"
51#include "SEQ_transform.hh"
52#include "SEQ_utils.hh"
53
54#include "DEG_depsgraph.hh"
56
57#include "ANIM_action.hh"
58#include "ANIM_action_legacy.hh"
59#include "ANIM_animdata.hh"
60
61#include "UI_view2d.hh"
62#include "WM_api.hh"
63#include "WM_types.hh"
64
65#ifdef WITH_AUDASPACE
66# include <AUD_Special.h>
67#endif
68
69/* Own include. */
70#include "sequencer_intern.hh"
71
72namespace blender::ed::vse {
73
74using namespace bke::blendfile;
75
76/* -------------------------------------------------------------------- */
77/* Copy Operator Helper functions
78 */
79
81 Strip *strip_dst,
82 ListBase *clipboard_dst,
83 ListBase *fcurve_base_src)
84{
85 /* Add curves for strips inside meta strip. */
86 if (strip_dst->type == STRIP_TYPE_META) {
87 LISTBASE_FOREACH (Strip *, meta_child, &strip_dst->seqbase) {
88 sequencer_copy_animation_listbase(scene_src, meta_child, clipboard_dst, fcurve_base_src);
89 }
90 }
91
93 *fcurve_base_src,
94 [&](const FCurve &fcurve) { return seq::fcurve_matches(*strip_dst, fcurve); });
95
96 for (FCurve *fcu_src : fcurves_src) {
97 BLI_addtail(clipboard_dst, BKE_fcurve_copy(fcu_src));
98 }
99}
100
101/* This is effectively just a copy of `sequencer_copy_animation_listbase()`
102 * above, except that it copies from an action's animation to a vector rather
103 * than between two listbases. */
105 Strip *strip_dst,
106 Vector<FCurve *> &clipboard_dst,
107 bAction &fcurves_src_action,
108 animrig::slot_handle_t fcurves_src_slot_handle)
109{
110 /* Add curves for strips inside meta strip. */
111 if (strip_dst->type == STRIP_TYPE_META) {
112 LISTBASE_FOREACH (Strip *, meta_child, &strip_dst->seqbase) {
114 scene_src, meta_child, clipboard_dst, fcurves_src_action, fcurves_src_slot_handle);
115 }
116 }
117
119 &fcurves_src_action, fcurves_src_slot_handle, [&](const FCurve &fcurve) {
120 return seq::fcurve_matches(*strip_dst, fcurve);
121 });
122
123 for (FCurve *fcu_src : fcurves_src) {
124 FCurve *fcu_copy = BKE_fcurve_copy(fcu_src);
125
126 /* Handling groups properly requires more work, so for now just ignore them. */
127 fcu_copy->grp = nullptr;
128
129 clipboard_dst.append(fcu_copy);
130 }
131}
132
133static void sequencer_copy_animation(Scene *scene_src,
134 Vector<FCurve *> &fcurves_dst,
135 ListBase *drivers_dst,
136 Strip *strip_dst)
137{
138 if (seq::animation_keyframes_exist(scene_src)) {
140 scene_src, strip_dst, fcurves_dst, *scene_src->adt->action, scene_src->adt->slot_handle);
141 }
142 if (seq::animation_drivers_exist(scene_src)) {
143 sequencer_copy_animation_listbase(scene_src, strip_dst, drivers_dst, &scene_src->adt->drivers);
144 }
145}
146
147static void sequencer_copybuffer_filepath_get(char filepath[FILE_MAX], size_t filepath_maxncpy)
148{
149 BLI_path_join(filepath, filepath_maxncpy, BKE_tempdir_base(), "copybuffer_vse.blend");
150}
151
153 Scene *scene_src,
154 const char *filepath,
155 ReportList &reports)
156
157{
158 /* NOTE: Setting the same current file path as G_MAIN is necessary for now to get correct
159 * external filepaths when writing the partial write context on disk. otherwise, filepaths from
160 * the scene's sequencer strips (e.g. image ones) would also need to be remapped in this code. */
161 PartialWriteContext copy_buffer{*bmain_src};
162 const char *scene_name = "copybuffer_vse_scene";
163
164 /* Add a dummy empty scene to the temporary Main copy buffer. */
165 Scene *scene_dst = reinterpret_cast<Scene *>(
166 copy_buffer.id_create(ID_SCE,
167 scene_name,
168 nullptr,
169 {(PartialWriteContext::IDAddOperations::SET_FAKE_USER |
170 PartialWriteContext::IDAddOperations::SET_CLIPBOARD_MARK)}));
171
172 /* Create an empty sequence editor data to store all copied strips. */
173 scene_dst->ed = MEM_callocN<Editing>(__func__);
175 scene_src,
176 scene_dst,
177 &scene_dst->ed->seqbase,
178 scene_src->ed->current_strips(),
180 0);
181
182 BLI_duplicatelist(&scene_dst->ed->channels, &scene_src->ed->channels);
183
184 /* Save current frame and active strip. */
185 scene_dst->r.cfra = scene_src->r.cfra;
186 Strip *active_seq_src = seq::select_active_get(scene_src);
187 if (active_seq_src) {
188 Strip *strip_dst = static_cast<Strip *>(
189 BLI_findstring(&scene_dst->ed->seqbase, active_seq_src->name, offsetof(Strip, name)));
190 if (strip_dst) {
191 seq::select_active_set(scene_dst, strip_dst);
192 }
193 }
194
195 Vector<FCurve *> fcurves_dst = {};
196 ListBase drivers_dst = {nullptr, nullptr};
197 LISTBASE_FOREACH (Strip *, strip_dst, &scene_dst->ed->seqbase) {
198 /* Copy any fcurves/drivers from `scene_src` that are relevant to `strip_dst`. */
199 sequencer_copy_animation(scene_src, fcurves_dst, &drivers_dst, strip_dst);
200 }
201
202 BLI_assert(scene_dst->adt == nullptr);
203
204 /* Copy over the fcurves. */
205 if (!fcurves_dst.is_empty()) {
206 scene_dst->adt = BKE_animdata_ensure_id(&scene_dst->id);
207 animrig::Action &action_dst =
208 reinterpret_cast<bAction *>(
209 copy_buffer.id_create(
210 ID_AC, scene_name, nullptr, {PartialWriteContext::IDAddOperations::SET_FAKE_USER}))
211 ->wrap();
212
213 /* Assign the `dst_action` as either legacy or layered, depending on what
214 * the source action we're copying from is. */
216 const bool success = animrig::assign_action(&action_dst, scene_dst->id);
217 if (!success) {
218 return false;
219 }
220 }
221 else {
222 /* If we're copying from a layered action, also ensure a connected slot. */
224 scene_dst->id);
225 if (slot == nullptr) {
226 return false;
227 }
228 }
229
230 for (FCurve *fcurve : fcurves_dst) {
232 scene_dst->adt->slot_handle,
233 *fcurve,
234 fcurve->grp ? std::optional(fcurve->grp->name) : std::nullopt);
235 }
236 }
237
238 /* Copy over the drivers. */
239 if (!BLI_listbase_is_empty(&drivers_dst)) {
240 scene_dst->adt = BKE_animdata_ensure_id(&scene_dst->id);
241 BLI_movelisttolist(&scene_dst->adt->drivers, &drivers_dst);
242 }
243
244 /* Only add to the paste buffer some dependency ID types. For example, scenes are ignored/cleared
245 * (how to copy and paste scene strips is not clear currently).
246 */
247 /* NOTE: since a special Scene root ID needs to be forged for the VSE copy/paste (instead of
248 * directly using the current scene and adding it to the paste buffer), the first level of
249 * dependencies (IDs directly used by the scene) need to be processed manually here.
250 *
251 * All other indirect dependencies will then be handled automatically by the partial write
252 * context code.
253 */
254#define VSE_COPYBUFFER_IDTYPES ID_SO, ID_MC, ID_IM, ID_TXT, ID_VF, ID_AC
255 auto add_scene_ids_dependencies_cb = [&copy_buffer,
256 scene_dst](LibraryIDLinkCallbackData *cb_data) -> int {
257 ID *id_src = *cb_data->id_pointer;
258
259 /* Embedded or null IDs usages can be ignored here. */
260 if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_EMBEDDED_NOT_OWNING)) {
261 return IDWALK_RET_NOP;
262 }
263 if (!id_src) {
264 return IDWALK_RET_NOP;
265 }
266
267 /* The Action ID of the destination scene has already been added (created actually) in the copy
268 * buffer. This is necessary to ensure that only the relevant sequencer-related animation data
269 * is copied into the destination paste buffer, and not the whole scene's animation. See the
270 * code around the call to #sequencer_copy_animation above.
271 *
272 * So trying to add it again here would lead to serious issues. */
273 if (scene_dst->adt && scene_dst->adt->action == reinterpret_cast<bAction *>(id_src)) {
274 BLI_assert(GS(id_src->name) == ID_AC);
275 return IDWALK_RET_NOP;
276 }
277
278 ID *id_dst = nullptr;
279 const ID_Type id_type = GS((id_src)->name);
280 /* Only add (and follow) IDs which usage is marked as 'never null', or are from following
281 * types: #bSound, #MovieClip, #Image, #Text, #VFont, #bAction. */
282 if (ELEM(id_type, VSE_COPYBUFFER_IDTYPES) || (cb_data->cb_flag & IDWALK_CB_NEVER_NULL)) {
283 /* The partial write context handle dependencies of ID added to it. This callback will tell
284 * it whether a given dependency ID should be skipped/cleared, or also added in the context.
285 */
286 auto partial_write_dependencies_filter_cb = [](LibraryIDLinkCallbackData *cb_deps_data,
289 ID *id_deps_src = *cb_deps_data->id_pointer;
290 const ID_Type id_type = GS((id_deps_src)->name);
291 if (ELEM(id_type, VSE_COPYBUFFER_IDTYPES) ||
292 (cb_deps_data->cb_flag & IDWALK_CB_NEVER_NULL))
293 {
294 return PartialWriteContext::IDAddOperations::ADD_DEPENDENCIES;
295 }
296 return PartialWriteContext::IDAddOperations::CLEAR_DEPENDENCIES;
297 };
298 id_dst = copy_buffer.id_add(id_src,
299 {PartialWriteContext::IDAddOperations::NOP},
300 partial_write_dependencies_filter_cb);
301 }
302 *cb_data->id_pointer = id_dst;
303 return IDWALK_RET_NOP;
304 };
306 nullptr, &scene_dst->id, add_scene_ids_dependencies_cb, nullptr, IDWALK_NOP);
307#undef VSE_COPYBUFFER_IDTYPES
308
309 BLI_assert(copy_buffer.is_valid());
310
311 const bool retval = copy_buffer.write(filepath, reports);
312
313 return retval;
314}
315
317{
318 Main *bmain = CTX_data_main(C);
320 Editing *ed = seq::editing_get(scene);
321
322 blender::VectorSet<Strip *> selected = seq::query_selected_strips(ed->current_strips());
323
324 if (selected.is_empty()) {
325 return OPERATOR_CANCELLED;
326 }
327
328 blender::VectorSet<Strip *> effect_chain;
329 effect_chain.add_multiple(selected);
331 scene, ed->current_strips(), effect_chain, seq::query_strip_effect_chain);
332
334 for (Strip *strip : effect_chain) {
335 if (!(strip->flag & SELECT)) {
336 strip->flag |= SELECT;
337 expanded.add(strip);
338 }
339 }
340
341 char filepath[FILE_MAX];
342 sequencer_copybuffer_filepath_get(filepath, sizeof(filepath));
343 bool success = sequencer_write_copy_paste_file(bmain, scene, filepath, *op->reports);
344 if (!success) {
345 BKE_report(op->reports, RPT_ERROR, "Could not create the copy paste file!");
346 for (Strip *strip : expanded) {
347 strip->flag &= ~SELECT;
348 }
349 return OPERATOR_CANCELLED;
350 }
351
352 /* We are all done! */
353 if (effect_chain.size() > selected.size()) {
355 RPT_INFO,
356 "Copied the selected Video Sequencer strips and associated effect chain to "
357 "internal clipboard");
358 }
359 else {
361 op->reports, RPT_INFO, "Copied the selected Video Sequencer strips to internal clipboard");
362 }
365 return OPERATOR_FINISHED;
366}
367
368/* -------------------------------------------------------------------- */
369/* Paste Operator Helper functions
370 */
371
372static bool sequencer_paste_animation(Main *bmain_dst, Scene *scene_dst, Scene *scene_src)
373{
374 if (!seq::animation_keyframes_exist(scene_src) && !seq::animation_drivers_exist(scene_src)) {
375 return false;
376 }
377
378 bAction *act_dst = animrig::id_action_ensure(bmain_dst, &scene_dst->id);
379
380 /* For layered actions ensure we have an attached slot. */
383 scene_dst->id);
384 BLI_assert(slot != nullptr);
385 if (slot == nullptr) {
386 return false;
387 }
388 }
389
391 animrig::action_fcurve_attach(act_dst->wrap(),
392 scene_dst->adt->slot_handle,
393 *BKE_fcurve_copy(fcu),
394 fcu->grp ? std::optional(fcu->grp->name) : std::nullopt);
395 }
396 LISTBASE_FOREACH (FCurve *, fcu, &scene_src->adt->drivers) {
397 BLI_addtail(&scene_dst->adt->drivers, BKE_fcurve_copy(fcu));
398 }
399
400 return true;
401}
402
404 wmOperator *op,
405 const wmEvent *event)
406{
407 RNA_int_set(op->ptr, "x", event->mval[0]);
408 RNA_int_set(op->ptr, "y", event->mval[1]);
410}
411
413{
414 char filepath[FILE_MAX];
415 sequencer_copybuffer_filepath_get(filepath, sizeof(filepath));
417 BlendFileReadReport bf_reports{};
418 BlendFileData *bfd = BKE_blendfile_read(filepath, &params, &bf_reports);
419 const int mval[2] = {RNA_int_get(op->ptr, "x"), RNA_int_get(op->ptr, "y")};
420 float2 view_mval;
423 UI_view2d_region_to_view(v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]);
424
425 /* For checking if region type is Preview. */
426 ARegion *region = CTX_wm_region(C);
427
428 if (bfd == nullptr) {
429 BKE_report(op->reports, RPT_INFO, "No data to paste");
430 return OPERATOR_CANCELLED;
431 }
432
433 Main *bmain_src = bfd->main;
434 bfd->main = nullptr;
436
437 Scene *scene_src = nullptr;
438 /* Find the scene we pasted that contains the strips. It should be tagged. */
439 LISTBASE_FOREACH (Scene *, scene_iter, &bmain_src->scenes) {
440 if (scene_iter->id.flag & ID_FLAG_CLIPBOARD_MARK) {
441 scene_src = scene_iter;
442 break;
443 }
444 }
445
446 if (!scene_src || !scene_src->ed) {
447 BKE_report(op->reports, RPT_ERROR, "No clipboard scene to paste Video Sequencer data from");
448 BKE_main_free(bmain_src);
449 return OPERATOR_CANCELLED;
450 }
451
452 const int num_strips_to_paste = BLI_listbase_count(&scene_src->ed->seqbase);
453 if (num_strips_to_paste == 0) {
454 BKE_report(op->reports, RPT_INFO, "No strips to paste");
455 BKE_main_free(bmain_src);
456 return OPERATOR_CANCELLED;
457 }
458
459 Scene *scene_dst = CTX_data_sequencer_scene(C);
460 Editing *ed_dst = seq::editing_ensure(scene_dst); /* Creates "ed" if it's missing. */
461 int ofs;
462
463 deselect_all_strips(scene_dst);
464 if (RNA_boolean_get(op->ptr, "keep_offset") || (region->regiontype == RGN_TYPE_PREVIEW)) {
465 ofs = scene_dst->r.cfra - scene_src->r.cfra;
466 }
467 else {
468 int min_seq_startdisp = std::numeric_limits<int>::max();
469 LISTBASE_FOREACH (Strip *, strip, &scene_src->ed->seqbase) {
470 min_seq_startdisp = std::min(seq::time_left_handle_frame_get(scene_src, strip),
471 min_seq_startdisp);
472 }
473 /* Paste strips relative to the current-frame. */
474 ofs = scene_dst->r.cfra - min_seq_startdisp;
475 }
476
477 Strip *prev_active_seq = seq::select_active_get(scene_src);
478 std::string active_seq_name;
479 if (prev_active_seq) {
480 active_seq_name.assign(prev_active_seq->name);
481 }
482
483 /* Make sure we have all data IDs we need in bmain_dst. Remap the IDs if we already have them.
484 * This has to happen BEFORE we move the strip over to scene_dst. their ID mapping will not be
485 * correct otherwise. */
486 Main *bmain_dst = CTX_data_main(C);
487 MainMergeReport merge_reports = {};
488 /* NOTE: BKE_main_merge will free bmain_src! */
489 BKE_main_merge(bmain_dst, &bmain_src, merge_reports);
490
491 /* Paste animation.
492 * NOTE: Only fcurves and drivers are copied. NLA action strips are not copied.
493 * First backup original curves from scene and move curves from clipboard into scene. This way,
494 * when pasted strips are renamed, pasted fcurves are renamed with them. Finally restore original
495 * curves from backup.
496 */
497 seq::AnimationBackup animation_backup = {{nullptr}};
498 seq::animation_backup_original(scene_dst, &animation_backup);
499 bool has_animation = sequencer_paste_animation(bmain_dst, scene_dst, scene_src);
500
501 ListBase nseqbase = {nullptr, nullptr};
502 /* NOTE: seq::seqbase_duplicate_recursive() takes care of generating
503 * new UIDs for sequences in the new list. */
505 scene_src,
506 scene_dst,
507 &nseqbase,
508 &scene_src->ed->seqbase,
510 0);
511
512 /* BKE_main_merge will copy the scene_src and its action into bmain_dst. Remove them as
513 * we merge the data from these manually.
514 */
515 if (has_animation && scene_src->adt->action != nullptr) {
516 BKE_id_delete(bmain_dst, scene_src->adt->action);
517 }
518 BKE_id_delete(bmain_dst, scene_src);
519
520 Strip *iseq_first = static_cast<Strip *>(nseqbase.first);
521 BLI_movelisttolist(ed_dst->current_strips(), &nseqbase);
522 /* Restore "first" pointer as BLI_movelisttolist sets it to nullptr */
523 nseqbase.first = iseq_first;
524
525 int2 strip_mean_pos = {0, 0};
526 int image_strip_count = 0;
527 LISTBASE_FOREACH (Strip *, istrip, &nseqbase) {
528 if (istrip->name == active_seq_name) {
529 seq::select_active_set(scene_dst, istrip);
530 }
531 /* Make sure, that pasted strips have unique names. This has to be done after
532 * adding strips to seqbase, for lookup cache to work correctly. */
533 seq::ensure_unique_name(istrip, scene_dst);
534
535 if (region->regiontype == RGN_TYPE_PREVIEW && istrip->type != STRIP_TYPE_SOUND_RAM &&
537 {
538 strip_mean_pos += static_cast<int2>(
540 image_strip_count++;
541 }
542 }
543
544 if (image_strip_count > 0) {
545 strip_mean_pos /= image_strip_count;
546 }
547
548 LISTBASE_FOREACH (Strip *, istrip, &nseqbase) {
549 /* Place strips that generate an image at the mouse cursor. */
550 if (region->regiontype == RGN_TYPE_PREVIEW && !RNA_boolean_get(op->ptr, "keep_offset") &&
551 istrip->type != STRIP_TYPE_SOUND_RAM &&
553 {
554 StripTransform *transform = istrip->data->transform;
555 const float2 mirror = seq::image_transform_mirror_factor_get(istrip);
556 const float2 origin = seq::image_transform_origin_offset_pixelspace_get(scene, istrip);
557 transform->xofs = (view_mval[0] - (strip_mean_pos[0] - origin[0])) * mirror[0];
558 transform->yofs = (view_mval[1] - (strip_mean_pos[1] - origin[1])) * mirror[1];
559 seq::relations_invalidate_cache(scene, istrip);
560 }
561 /* Translate after name has been changed, otherwise this will affect animdata of original
562 * strip. */
563 seq::transform_translate_strip(scene_dst, istrip, ofs);
564 /* Ensure, that pasted strips don't overlap. */
565 if (seq::transform_test_overlap(scene_dst, ed_dst->current_strips(), istrip)) {
566 seq::transform_seqbase_shuffle(ed_dst->current_strips(), istrip, scene_dst);
567 }
568 }
569
570 seq::animation_restore_original(scene_dst, &animation_backup);
571
573 if (scene_dst->adt && scene_dst->adt->action) {
575 }
576 DEG_relations_tag_update(bmain_dst);
580
581 BKE_reportf(op->reports, RPT_INFO, "%d strips pasted", num_strips_to_paste);
582
583 return OPERATOR_FINISHED;
584}
585} // namespace blender::ed::vse
Functions and classes to work with Actions.
Functions for backward compatibility with the legacy Action API.
Functions to work with AnimData.
AnimData * BKE_animdata_ensure_id(ID *id)
Definition anim_data.cc:97
const char * BKE_tempdir_base() ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL
Definition appdir.cc:1243
BlendFileData * BKE_blendfile_read(const char *filepath, const BlendFileReadParams *params, BlendFileReadReport *reports)
Main * CTX_data_main(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
Scene * CTX_data_sequencer_scene(const bContext *C)
FCurve * BKE_fcurve_copy(const FCurve *fcu)
void BKE_id_delete(Main *bmain, void *idv) ATTR_NONNULL()
@ IDWALK_RET_NOP
@ IDWALK_CB_EMBEDDED_NOT_OWNING
@ IDWALK_CB_EMBEDDED
@ IDWALK_CB_NEVER_NULL
void BKE_library_foreach_ID_link(Main *bmain, ID *id, blender::FunctionRef< LibraryIDLinkCallback > callback, void *user_data, LibraryForeachIDFlag flag)
Definition lib_query.cc:431
@ IDWALK_NOP
void BKE_main_merge(Main *bmain_dst, Main **r_bmain_src, MainMergeReport &reports)
Definition main.cc:326
void BKE_main_free(Main *bmain)
Definition main.cc:192
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
@ RPT_INFO
Definition BKE_report.hh:35
@ RPT_ERROR
Definition BKE_report.hh:39
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
#define BLI_assert(a)
Definition BLI_assert.h:46
void void void BLI_movelisttolist(ListBase *dst, ListBase *src) ATTR_NONNULL(1
#define LISTBASE_FOREACH(type, var, list)
void * BLI_findstring(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:608
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
void void void void void void BLI_duplicatelist(ListBase *dst, const ListBase *src) ATTR_NONNULL(1
#define FILE_MAX
#define BLI_path_join(...)
#define ELEM(...)
external readfile function prototypes.
void BLO_blendfiledata_free(BlendFileData *bfd)
external writefile.cc function prototypes.
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
@ ID_RECALC_SEQUENCER_STRIPS
Definition DNA_ID.h:1122
@ ID_RECALC_ANIMATION_NO_FLUSH
Definition DNA_ID.h:1176
@ ID_FLAG_CLIPBOARD_MARK
Definition DNA_ID.h:799
ID_Type
@ ID_SCE
@ ID_AC
@ RGN_TYPE_PREVIEW
@ STRIP_TYPE_SOUND_RAM
@ STRIP_TYPE_META
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
void ED_outliner_select_sync_from_sequence_tag(const bContext *C)
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
View2D * UI_view2d_fromcontext(const bContext *C)
Definition view2d.cc:1855
void UI_view2d_region_to_view(const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
Definition view2d.cc:1668
#define ND_SEQUENCER
Definition WM_types.hh:437
#define NC_SCENE
Definition WM_types.hh:378
#define ND_ANIMCHAN
Definition WM_types.hh:496
#define NA_SELECTED
Definition WM_types.hh:589
bool add(const Key &key)
void add_multiple(Span< Key > keys)
int64_t size() const
void append(const T &value)
bool is_empty() const
ID * id_add(const ID *id, IDAddOptions options, blender::FunctionRef< IDAddOperations(LibraryIDLinkCallbackData *cb_data, IDAddOptions options)> dependencies_filter_cb=nullptr)
bool write(const char *write_filepath, int write_flags, int remap_mode, ReportList &reports)
ID * id_create(short id_type, StringRefNull id_name, Library *library, IDAddOptions options)
#define SELECT
#define offsetof(t, d)
#define GS(x)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
Vector< FCurve * > fcurves_for_assigned_action(AnimData *adt)
bool action_treat_as_legacy(const bAction &action)
void action_fcurve_attach(Action &action, slot_handle_t action_slot, FCurve &fcurve_to_attach, std::optional< StringRefNull > group_name)
Vector< FCurve * > fcurves_in_listbase_filtered(ListBase fcurves, FunctionRef< bool(const FCurve &fcurve)> predicate)
Vector< FCurve * > fcurves_in_action_slot_filtered(bAction *act, slot_handle_t slot_handle, FunctionRef< bool(const FCurve &fcurve)> predicate)
Slot * assign_action_ensure_slot_for_keying(Action &action, ID &animated_id)
bAction * id_action_ensure(Main *bmain, ID *id)
Definition animdata.cc:195
decltype(::ActionSlot::handle) slot_handle_t
bool assign_action(bAction *action, ID &animated_id)
static void sequencer_copybuffer_filepath_get(char filepath[FILE_MAX], size_t filepath_maxncpy)
static void sequencer_copy_animation_to_vector(Scene *scene_src, Strip *strip_dst, Vector< FCurve * > &clipboard_dst, bAction &fcurves_src_action, animrig::slot_handle_t fcurves_src_slot_handle)
wmOperatorStatus sequencer_clipboard_copy_exec(bContext *C, wmOperator *op)
static bool sequencer_paste_animation(Main *bmain_dst, Scene *scene_dst, Scene *scene_src)
static void sequencer_copy_animation_listbase(Scene *scene_src, Strip *strip_dst, ListBase *clipboard_dst, ListBase *fcurve_base_src)
static bool sequencer_write_copy_paste_file(Main *bmain_src, Scene *scene_src, const char *filepath, ReportList &reports)
bool deselect_all_strips(const Scene *scene)
wmOperatorStatus sequencer_clipboard_paste_exec(bContext *C, wmOperator *op)
wmOperatorStatus sequencer_clipboard_paste_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void sequencer_copy_animation(Scene *scene_src, Vector< FCurve * > &fcurves_dst, ListBase *drivers_dst, Strip *strip_dst)
VectorSet< Strip * > query_all_strips(ListBase *seqbase)
Definition iterator.cc:143
void relations_invalidate_cache(Scene *scene, Strip *strip)
VectorSet< Strip * > query_selected_strips(ListBase *seqbase)
Definition iterator.cc:152
void transform_translate_strip(Scene *evil_scene, Strip *strip, int delta)
bool animation_keyframes_exist(const Scene *scene)
Definition animation.cc:25
bool transform_test_overlap(const Scene *scene, Strip *strip1, Strip *strip2)
Editing * editing_get(const Scene *scene)
Definition sequencer.cc:286
int time_left_handle_frame_get(const Scene *, const Strip *strip)
float2 image_transform_mirror_factor_get(const Strip *strip)
bool animation_drivers_exist(Scene *scene)
Definition animation.cc:31
void query_strip_effect_chain(const Scene *scene, Strip *reference_strip, ListBase *seqbase, VectorSet< Strip * > &r_strips)
Definition iterator.cc:254
Editing * editing_ensure(Scene *scene)
Definition sequencer.cc:291
Strip * select_active_get(const Scene *scene)
void iterator_set_expand(const Scene *scene, ListBase *seqbase, VectorSet< Strip * > &strips, void strip_query_func(const Scene *scene, Strip *strip_reference, ListBase *seqbase, VectorSet< Strip * > &strips))
Definition iterator.cc:82
float2 image_transform_origin_offset_pixelspace_get(const Scene *scene, const Strip *strip)
void animation_backup_original(Scene *scene, AnimationBackup *backup)
Definition animation.cc:91
void select_active_set(Scene *scene, Strip *strip)
bool must_render_strip(const VectorSet< Strip * > &strips, Strip *strip)
Definition iterator.cc:184
void animation_restore_original(Scene *scene, AnimationBackup *backup)
Definition animation.cc:113
bool fcurve_matches(const Strip &strip, const FCurve &fcurve)
Definition animation.cc:36
void ensure_unique_name(Strip *strip, Scene *scene)
bool transform_seqbase_shuffle(ListBase *seqbasep, Strip *test, Scene *evil_scene)
void seqbase_duplicate_recursive(Main *bmain, const Scene *scene_src, Scene *scene_dst, ListBase *nseqbase, const ListBase *seqbase, const StripDuplicate dupe_flag, const int flag)
Definition sequencer.cc:819
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
float wrap(float value, float max, float min)
Definition node_math.h:103
const char * name
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
int RNA_int_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
#define VSE_COPYBUFFER_IDTYPES
bAction * action
int32_t slot_handle
ListBase drivers
ListBase seqbase
ListBase channels
bActionGroup * grp
Definition DNA_ID.h:414
char name[258]
Definition DNA_ID.h:432
LibraryForeachIDCallbackFlag cb_flag
void * first
ListBase scenes
Definition BKE_main.hh:278
struct Editing * ed
struct RenderData r
struct AnimData * adt
ListBase seqbase
char name[64]
int mval[2]
Definition WM_types.hh:763
struct ReportList * reports
struct PointerRNA * ptr
void WM_event_add_notifier(const bContext *C, uint type, void *reference)