forked from bartvdbraak/blender
fix [#36262] Paste strip with video or sound content from another file crashes Blender
existing code was very stupid. - all ID pointers for clipboard strips are handled uniformly. - clipboard stores a duplicate ID pointer which are restored on paste. - restoring pointers... -- use ID's that are still in the database (copy&paste within the same file). -- fallback to name lookup. -- fallback to loading them from the original filepath (movie-clip and sound only). also fix bug pasting where initialing the sound wasn't done if there was no frame-offset.
This commit is contained in:
parent
d0f225393c
commit
576161b186
@ -671,13 +671,14 @@ class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel):
|
|||||||
layout.separator()
|
layout.separator()
|
||||||
layout.prop(strip, "filepath", text="")
|
layout.prop(strip, "filepath", text="")
|
||||||
|
|
||||||
row = layout.row()
|
if sound is not None:
|
||||||
if sound.packed_file:
|
row = layout.row()
|
||||||
row.operator("sound.unpack", icon='PACKAGE', text="Unpack")
|
if sound.packed_file:
|
||||||
else:
|
row.operator("sound.unpack", icon='PACKAGE', text="Unpack")
|
||||||
row.operator("sound.pack", icon='UGLYPACKAGE', text="Pack")
|
else:
|
||||||
|
row.operator("sound.pack", icon='UGLYPACKAGE', text="Pack")
|
||||||
|
|
||||||
row.prop(sound, "use_memory_cache")
|
row.prop(sound, "use_memory_cache")
|
||||||
|
|
||||||
layout.prop(strip, "show_waveform")
|
layout.prop(strip, "show_waveform")
|
||||||
layout.prop(strip, "volume")
|
layout.prop(strip, "volume")
|
||||||
|
@ -208,6 +208,10 @@ int BKE_sequencer_recursive_apply(struct Sequence *seq, int (*apply_func)(struct
|
|||||||
|
|
||||||
void BKE_sequencer_free_clipboard(void);
|
void BKE_sequencer_free_clipboard(void);
|
||||||
|
|
||||||
|
void BKE_sequence_clipboard_pointers_free(struct Sequence *seq);
|
||||||
|
void BKE_sequence_clipboard_pointers_store(struct Sequence *seq);
|
||||||
|
void BKE_sequence_clipboard_pointers_restore(struct Sequence *seq, struct Main *bmain);
|
||||||
|
|
||||||
void BKE_sequence_free(struct Scene *scene, struct Sequence *seq);
|
void BKE_sequence_free(struct Scene *scene, struct Sequence *seq);
|
||||||
const char *BKE_sequence_give_name(struct Sequence *seq);
|
const char *BKE_sequence_give_name(struct Sequence *seq);
|
||||||
void BKE_sequence_calc(struct Scene *scene, struct Sequence *seq);
|
void BKE_sequence_calc(struct Scene *scene, struct Sequence *seq);
|
||||||
@ -319,8 +323,6 @@ void BKE_sequence_base_dupli_recursive(struct Scene *scene, struct Scene *scene_
|
|||||||
bool BKE_sequence_is_valid_check(struct Sequence *seq);
|
bool BKE_sequence_is_valid_check(struct Sequence *seq);
|
||||||
|
|
||||||
void BKE_sequencer_clear_scene_in_allseqs(struct Main *bmain, struct Scene *sce);
|
void BKE_sequencer_clear_scene_in_allseqs(struct Main *bmain, struct Scene *sce);
|
||||||
void BKE_sequencer_clear_movieclip_in_clipboard(struct MovieClip *clip);
|
|
||||||
void BKE_sequencer_clear_mask_in_clipboard(struct Mask *mask);
|
|
||||||
|
|
||||||
struct Sequence *BKE_sequence_get_by_name(struct ListBase *seqbase, const char *name, int recursive);
|
struct Sequence *BKE_sequence_get_by_name(struct ListBase *seqbase, const char *name, int recursive);
|
||||||
|
|
||||||
|
@ -939,8 +939,6 @@ void BKE_mask_free(Main *bmain, Mask *mask)
|
|||||||
SpaceLink *sl;
|
SpaceLink *sl;
|
||||||
Scene *scene;
|
Scene *scene;
|
||||||
|
|
||||||
BKE_sequencer_clear_mask_in_clipboard(mask);
|
|
||||||
|
|
||||||
for (scr = bmain->screen.first; scr; scr = scr->id.next) {
|
for (scr = bmain->screen.first; scr; scr = scr->id.next) {
|
||||||
for (area = scr->areabase.first; area; area = area->next) {
|
for (area = scr->areabase.first; area; area = area->next) {
|
||||||
for (sl = area->spacedata.first; sl; sl = sl->next) {
|
for (sl = area->spacedata.first; sl; sl = sl->next) {
|
||||||
|
@ -1395,8 +1395,6 @@ void BKE_movieclip_build_proxy_frame_for_ibuf(MovieClip *clip, ImBuf *ibuf, stru
|
|||||||
|
|
||||||
void BKE_movieclip_free(MovieClip *clip)
|
void BKE_movieclip_free(MovieClip *clip)
|
||||||
{
|
{
|
||||||
BKE_sequencer_clear_movieclip_in_clipboard(clip);
|
|
||||||
|
|
||||||
free_buffers(clip);
|
free_buffers(clip);
|
||||||
|
|
||||||
BKE_tracking_free(&clip->tracking);
|
BKE_tracking_free(&clip->tracking);
|
||||||
|
@ -65,6 +65,7 @@
|
|||||||
#include "BKE_fcurve.h"
|
#include "BKE_fcurve.h"
|
||||||
#include "BKE_scene.h"
|
#include "BKE_scene.h"
|
||||||
#include "BKE_mask.h"
|
#include "BKE_mask.h"
|
||||||
|
#include "BKE_library.h"
|
||||||
|
|
||||||
#include "RNA_access.h"
|
#include "RNA_access.h"
|
||||||
|
|
||||||
@ -265,6 +266,7 @@ static void seq_free_clipboard_recursive(Sequence *seq_parent)
|
|||||||
seq_free_clipboard_recursive(seq);
|
seq_free_clipboard_recursive(seq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BKE_sequence_clipboard_pointers_free(seq_parent);
|
||||||
BKE_sequence_free_ex(NULL, seq_parent, FALSE);
|
BKE_sequence_free_ex(NULL, seq_parent, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,6 +281,101 @@ void BKE_sequencer_free_clipboard(void)
|
|||||||
seqbase_clipboard.first = seqbase_clipboard.last = NULL;
|
seqbase_clipboard.first = seqbase_clipboard.last = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
#define ID_PT (*id_pt)
|
||||||
|
static void seqclipboard_ptr_free(ID **id_pt)
|
||||||
|
{
|
||||||
|
if (ID_PT) {
|
||||||
|
BLI_assert(ID_PT->newid != NULL);
|
||||||
|
MEM_freeN(ID_PT);
|
||||||
|
ID_PT = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void seqclipboard_ptr_store(ID **id_pt)
|
||||||
|
{
|
||||||
|
if (ID_PT) {
|
||||||
|
ID *id_prev = ID_PT;
|
||||||
|
ID_PT = 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 != NULL);
|
||||||
|
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 == NULL) {
|
||||||
|
/* check for a data with the same filename */
|
||||||
|
switch (GS(ID_PT->name)) {
|
||||||
|
case ID_SO:
|
||||||
|
{
|
||||||
|
id_restore = BLI_findstring(lb, ((bSound *)ID_PT)->name, offsetof(bSound, name));
|
||||||
|
if (id_restore == NULL) {
|
||||||
|
id_restore = sound_new_file(bmain, ((bSound *)ID_PT)->name);
|
||||||
|
(ID_PT)->newid = id_restore; /* reuse next time */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ID_MC:
|
||||||
|
{
|
||||||
|
id_restore = BLI_findstring(lb, ((MovieClip *)ID_PT)->name, offsetof(MovieClip, name));
|
||||||
|
if (id_restore == NULL) {
|
||||||
|
id_restore = BKE_movieclip_file_add(bmain, ((MovieClip *)ID_PT)->name);
|
||||||
|
(ID_PT)->newid = id_restore; /* reuse next time */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ID_PT = id_restore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#undef ID_PT
|
||||||
|
|
||||||
|
void BKE_sequence_clipboard_pointers_free(Sequence *seq)
|
||||||
|
{
|
||||||
|
seqclipboard_ptr_free((ID **)&seq->scene);
|
||||||
|
seqclipboard_ptr_free((ID **)&seq->scene_camera);
|
||||||
|
seqclipboard_ptr_free((ID **)&seq->clip);
|
||||||
|
seqclipboard_ptr_free((ID **)&seq->mask);
|
||||||
|
seqclipboard_ptr_free((ID **)&seq->sound);
|
||||||
|
}
|
||||||
|
void BKE_sequence_clipboard_pointers_store(Sequence *seq)
|
||||||
|
{
|
||||||
|
seqclipboard_ptr_store((ID **)&seq->scene);
|
||||||
|
seqclipboard_ptr_store((ID **)&seq->scene_camera);
|
||||||
|
seqclipboard_ptr_store((ID **)&seq->clip);
|
||||||
|
seqclipboard_ptr_store((ID **)&seq->mask);
|
||||||
|
seqclipboard_ptr_store((ID **)&seq->sound);
|
||||||
|
}
|
||||||
|
void BKE_sequence_clipboard_pointers_restore(Sequence *seq, Main *bmain)
|
||||||
|
{
|
||||||
|
seqclipboard_ptr_restore(bmain, (ID **)&seq->scene);
|
||||||
|
seqclipboard_ptr_restore(bmain, (ID **)&seq->scene_camera);
|
||||||
|
seqclipboard_ptr_restore(bmain, (ID **)&seq->clip);
|
||||||
|
seqclipboard_ptr_restore(bmain, (ID **)&seq->mask);
|
||||||
|
seqclipboard_ptr_restore(bmain, (ID **)&seq->sound);
|
||||||
|
}
|
||||||
|
/* end clipboard pointer mess */
|
||||||
|
|
||||||
|
|
||||||
Editing *BKE_sequencer_editing_ensure(Scene *scene)
|
Editing *BKE_sequencer_editing_ensure(Scene *scene)
|
||||||
{
|
{
|
||||||
if (scene->ed == NULL) {
|
if (scene->ed == NULL) {
|
||||||
@ -818,33 +915,6 @@ void BKE_sequencer_clear_scene_in_allseqs(Main *bmain, Scene *scene)
|
|||||||
BKE_sequencer_base_recursive_apply(&scene_iter->ed->seqbase, clear_scene_in_allseqs_cb, scene);
|
BKE_sequencer_base_recursive_apply(&scene_iter->ed->seqbase, clear_scene_in_allseqs_cb, scene);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* also clear clipboard */
|
|
||||||
BKE_sequencer_base_recursive_apply(&seqbase_clipboard, clear_scene_in_allseqs_cb, scene);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int clear_movieclip_in_clipboard_cb(Sequence *seq, void *arg_pt)
|
|
||||||
{
|
|
||||||
if (seq->clip == (MovieClip *)arg_pt)
|
|
||||||
seq->clip = NULL;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BKE_sequencer_clear_movieclip_in_clipboard(MovieClip *clip)
|
|
||||||
{
|
|
||||||
BKE_sequencer_base_recursive_apply(&seqbase_clipboard, clear_movieclip_in_clipboard_cb, clip);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int clear_mask_in_clipboard_cb(Sequence *seq, void *arg_pt)
|
|
||||||
{
|
|
||||||
if (seq->mask == (Mask *)arg_pt)
|
|
||||||
seq->mask = NULL;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BKE_sequencer_clear_mask_in_clipboard(Mask *mask)
|
|
||||||
{
|
|
||||||
BKE_sequencer_base_recursive_apply(&seqbase_clipboard, clear_mask_in_clipboard_cb, mask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct SeqUniqueInfo {
|
typedef struct SeqUniqueInfo {
|
||||||
|
@ -5803,21 +5803,23 @@ static void *restore_pointer_by_name(Main *mainp, ID *id, int user)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void lib_link_seq_clipboard_pt_restore(ID *id, Main *newmain)
|
||||||
|
{
|
||||||
|
if (id) {
|
||||||
|
/* clipboard must ensure this */
|
||||||
|
BLI_assert(id->newid != NULL);
|
||||||
|
id->newid = restore_pointer_by_name(newmain, (ID *)id->newid, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
static int lib_link_seq_clipboard_cb(Sequence *seq, void *arg_pt)
|
static int lib_link_seq_clipboard_cb(Sequence *seq, void *arg_pt)
|
||||||
{
|
{
|
||||||
Main *newmain = (Main *)arg_pt;
|
Main *newmain = (Main *)arg_pt;
|
||||||
|
|
||||||
if (seq->sound) {
|
lib_link_seq_clipboard_pt_restore((ID *)seq->scene, newmain);
|
||||||
seq->sound = restore_pointer_by_name(newmain, (ID *)seq->sound, 0);
|
lib_link_seq_clipboard_pt_restore((ID *)seq->scene_camera, newmain);
|
||||||
seq->sound->id.us++;
|
lib_link_seq_clipboard_pt_restore((ID *)seq->clip, newmain);
|
||||||
}
|
lib_link_seq_clipboard_pt_restore((ID *)seq->mask, newmain);
|
||||||
|
lib_link_seq_clipboard_pt_restore((ID *)seq->sound, newmain);
|
||||||
if (seq->scene)
|
|
||||||
seq->scene = restore_pointer_by_name(newmain, (ID *)seq->scene, 1);
|
|
||||||
|
|
||||||
if (seq->scene_camera)
|
|
||||||
seq->scene_camera = restore_pointer_by_name(newmain, (ID *)seq->scene_camera, 1);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2721,7 +2721,6 @@ static void seq_copy_del_sound(Scene *scene, Sequence *seq)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO, validate scenes */
|
|
||||||
static int sequencer_copy_exec(bContext *C, wmOperator *op)
|
static int sequencer_copy_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
Scene *scene = CTX_data_scene(C);
|
Scene *scene = CTX_data_scene(C);
|
||||||
@ -2766,6 +2765,11 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op)
|
|||||||
for (seq = seqbase_clipboard.first; seq; seq = seq->next) {
|
for (seq = seqbase_clipboard.first; seq; seq = seq->next) {
|
||||||
seq_copy_del_sound(scene, seq);
|
seq_copy_del_sound(scene, seq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* duplicate pointers */
|
||||||
|
for (seq = seqbase_clipboard.first; seq; seq = seq->next) {
|
||||||
|
BKE_sequence_clipboard_pointers_store(seq);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
@ -2790,6 +2794,7 @@ void SEQUENCER_OT_copy(wmOperatorType *ot)
|
|||||||
|
|
||||||
static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op))
|
static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op))
|
||||||
{
|
{
|
||||||
|
Main *bmain = CTX_data_main(C);
|
||||||
Scene *scene = CTX_data_scene(C);
|
Scene *scene = CTX_data_scene(C);
|
||||||
Editing *ed = BKE_sequencer_editing_get(scene, TRUE); /* create if needed */
|
Editing *ed = BKE_sequencer_editing_get(scene, TRUE); /* create if needed */
|
||||||
ListBase nseqbase = {NULL, NULL};
|
ListBase nseqbase = {NULL, NULL};
|
||||||
@ -2805,10 +2810,17 @@ static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op))
|
|||||||
if (ofs) {
|
if (ofs) {
|
||||||
for (iseq = nseqbase.first; iseq; iseq = iseq->next) {
|
for (iseq = nseqbase.first; iseq; iseq = iseq->next) {
|
||||||
BKE_sequence_translate(scene, iseq, ofs);
|
BKE_sequence_translate(scene, iseq, ofs);
|
||||||
BKE_sequence_sound_init(scene, iseq);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (iseq = nseqbase.first; iseq; iseq = iseq->next) {
|
||||||
|
BKE_sequence_clipboard_pointers_restore(iseq, bmain);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (iseq = nseqbase.first; iseq; iseq = iseq->next) {
|
||||||
|
BKE_sequence_sound_init(scene, iseq);
|
||||||
|
}
|
||||||
|
|
||||||
iseq_first = nseqbase.first;
|
iseq_first = nseqbase.first;
|
||||||
|
|
||||||
BLI_movelisttolist(ed->seqbasep, &nseqbase);
|
BLI_movelisttolist(ed->seqbasep, &nseqbase);
|
||||||
|
Loading…
Reference in New Issue
Block a user