Sequencer: refactor clipboard copy to no longer increase user count.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Fri, 28 Dec 2018 12:37:51 +0000 (13:37 +0100)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Wed, 23 Jan 2019 11:06:58 +0000 (12:06 +0100)
The clipboard is not a real user and should not be counted. Only on paste
should the user count increase.

This is part of D3621, and was implemented by Richard Antalik and me.

source/blender/blenkernel/BKE_sequencer.h
source/blender/blenkernel/intern/seqeffects.c
source/blender/blenkernel/intern/sequencer.c
source/blender/editors/space_sequencer/sequencer_edit.c

index d395fca..2f78b36 100644 (file)
@@ -145,10 +145,10 @@ struct SeqEffectHandle {
        void (*load)(struct Sequence *seq);
 
        /* duplicate */
-       void (*copy)(struct Sequence *dst, struct Sequence *src);
+       void (*copy)(struct Sequence *dst, struct Sequence *src, const int flag);
 
        /* destruct */
-       void (*free)(struct Sequence *seq);
+       void (*free)(struct Sequence *seq, const bool do_id_user);
 
        /* returns: -1: no input needed,
         * 0: no early out,
@@ -226,12 +226,8 @@ int BKE_sequencer_recursive_apply(struct Sequence *seq, int (*apply_func)(struct
 
 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_sequencer_base_clipboard_pointers_free(struct ListBase *seqbase);
-void BKE_sequencer_base_clipboard_pointers_store(struct ListBase *seqbase);
+void BKE_sequencer_base_clipboard_pointers_store(struct Main *bmain, struct ListBase *seqbase);
 void BKE_sequencer_base_clipboard_pointers_restore(struct ListBase *seqbase, struct Main *bmain);
 
 void BKE_sequence_free(struct Scene *scene, struct Sequence *seq);
index c69f8ff..5ac83a6 100644 (file)
@@ -751,7 +751,7 @@ static void load_gammacross(Sequence *UNUSED(seq))
 {
 }
 
-static void free_gammacross(Sequence *UNUSED(seq))
+static void free_gammacross(Sequence *UNUSED(seq), const bool UNUSED(do_id_user))
 {
 }
 
@@ -1875,7 +1875,7 @@ static int num_inputs_wipe(void)
        return 2;
 }
 
-static void free_wipe_effect(Sequence *seq)
+static void free_wipe_effect(Sequence *seq, const bool UNUSED(do_id_user))
 {
        if (seq->effectdata)
                MEM_freeN(seq->effectdata);
@@ -1883,7 +1883,7 @@ static void free_wipe_effect(Sequence *seq)
        seq->effectdata = NULL;
 }
 
-static void copy_wipe_effect(Sequence *dst, Sequence *src)
+static void copy_wipe_effect(Sequence *dst, Sequence *src, const int UNUSED(flag))
 {
        dst->effectdata = MEM_dupallocN(src->effectdata);
 }
@@ -2066,13 +2066,13 @@ static int num_inputs_transform(void)
        return 1;
 }
 
-static void free_transform_effect(Sequence *seq)
+static void free_transform_effect(Sequence *seq, const bool UNUSED(do_id_user))
 {
        if (seq->effectdata) MEM_freeN(seq->effectdata);
        seq->effectdata = NULL;
 }
 
-static void copy_transform_effect(Sequence *dst, Sequence *src)
+static void copy_transform_effect(Sequence *dst, Sequence *src, const int UNUSED(flag))
 {
        dst->effectdata = MEM_dupallocN(src->effectdata);
 }
@@ -2384,7 +2384,7 @@ static int num_inputs_glow(void)
        return 1;
 }
 
-static void free_glow_effect(Sequence *seq)
+static void free_glow_effect(Sequence *seq, const bool UNUSED(do_id_user))
 {
        if (seq->effectdata)
                MEM_freeN(seq->effectdata);
@@ -2392,7 +2392,7 @@ static void free_glow_effect(Sequence *seq)
        seq->effectdata = NULL;
 }
 
-static void copy_glow_effect(Sequence *dst, Sequence *src)
+static void copy_glow_effect(Sequence *dst, Sequence *src, const int UNUSED(flag))
 {
        dst->effectdata = MEM_dupallocN(src->effectdata);
 }
@@ -2478,7 +2478,7 @@ static int num_inputs_color(void)
        return 0;
 }
 
-static void free_solid_color(Sequence *seq)
+static void free_solid_color(Sequence *seq, const bool UNUSED(do_id_user))
 {
        if (seq->effectdata)
                MEM_freeN(seq->effectdata);
@@ -2486,7 +2486,7 @@ static void free_solid_color(Sequence *seq)
        seq->effectdata = NULL;
 }
 
-static void copy_solid_color(Sequence *dst, Sequence *src)
+static void copy_solid_color(Sequence *dst, Sequence *src, const int UNUSED(flag))
 {
        dst->effectdata = MEM_dupallocN(src->effectdata);
 }
@@ -2734,7 +2734,7 @@ static int num_inputs_speed(void)
        return 1;
 }
 
-static void free_speed_effect(Sequence *seq)
+static void free_speed_effect(Sequence *seq, const bool UNUSED(do_id_user))
 {
        SpeedControlVars *v = (SpeedControlVars *)seq->effectdata;
        if (v->frameMap)
@@ -2744,7 +2744,7 @@ static void free_speed_effect(Sequence *seq)
        seq->effectdata = NULL;
 }
 
-static void copy_speed_effect(Sequence *dst, Sequence *src)
+static void copy_speed_effect(Sequence *dst, Sequence *src, const int UNUSED(flag))
 {
        SpeedControlVars *v;
        dst->effectdata = MEM_dupallocN(src->effectdata);
@@ -2959,7 +2959,7 @@ static int num_inputs_gaussian_blur(void)
        return 1;
 }
 
-static void free_gaussian_blur_effect(Sequence *seq)
+static void free_gaussian_blur_effect(Sequence *seq, const bool UNUSED(do_id_user))
 {
        if (seq->effectdata)
                MEM_freeN(seq->effectdata);
@@ -2967,7 +2967,7 @@ static void free_gaussian_blur_effect(Sequence *seq)
        seq->effectdata = NULL;
 }
 
-static void copy_gaussian_blur_effect(Sequence *dst, Sequence *src)
+static void copy_gaussian_blur_effect(Sequence *dst, Sequence *src, const int UNUSED(flag))
 {
        dst->effectdata = MEM_dupallocN(src->effectdata);
 }
@@ -3573,7 +3573,7 @@ static void load_noop(Sequence *UNUSED(seq))
 
 }
 
-static void free_noop(Sequence *UNUSED(seq))
+static void free_noop(Sequence *UNUSED(seq), const bool UNUSED(do_id_user))
 {
 
 }
@@ -3583,12 +3583,12 @@ static int num_inputs_default(void)
        return 2;
 }
 
-static void copy_effect_default(Sequence *dst, Sequence *src)
+static void copy_effect_default(Sequence *dst, Sequence *src, const int UNUSED(flag))
 {
        dst->effectdata = MEM_dupallocN(src->effectdata);
 }
 
-static void free_effect_default(Sequence *seq)
+static void free_effect_default(Sequence *seq, const bool UNUSED(do_id_user))
 {
        if (seq->effectdata)
                MEM_freeN(seq->effectdata);
index 21d092e..92e974b 100644 (file)
@@ -209,8 +209,7 @@ static void BKE_sequence_free_ex(Scene *scene, Sequence *seq, const bool do_cach
 
        if (seq->type & SEQ_TYPE_EFFECT) {
                struct SeqEffectHandle sh = BKE_sequence_get_effect(seq);
-
-               sh.free(seq);
+               sh.free(seq, do_id_user);
        }
 
        if (seq->sound && do_id_user) {
@@ -283,16 +282,16 @@ void BKE_sequence_free_anim(Sequence *seq)
 
 /* cache must be freed before calling this function
  * since it leaves the seqbase in an invalid state */
-static void seq_free_sequence_recurse(Scene *scene, Sequence *seq)
+static void seq_free_sequence_recurse(Scene *scene, Sequence *seq, const bool do_id_user)
 {
        Sequence *iseq, *iseq_next;
 
        for (iseq = seq->seqbase.first; iseq; iseq = iseq_next) {
                iseq_next = iseq->next;
-               seq_free_sequence_recurse(scene, iseq);
+               seq_free_sequence_recurse(scene, iseq, do_id_user);
        }
 
-       BKE_sequence_free_ex(scene, seq, false, true);
+       BKE_sequence_free_ex(scene, seq, false, do_id_user);
 }
 
 
@@ -312,7 +311,7 @@ void BKE_sequencer_free_clipboard(void)
 
        for (seq = seqbase_clipboard.first; seq; seq = nseq) {
                nseq = seq->next;
-               seq_free_sequence_recurse(NULL, seq);
+               seq_free_sequence_recurse(NULL, seq, false);
        }
        BLI_listbase_clear(&seqbase_clipboard);
 }
@@ -325,7 +324,7 @@ void BKE_sequencer_free_clipboard(void)
  * since those datablocks are fully out of Main lists).
  */
 #define ID_PT (*id_pt)
-static void seqclipboard_ptr_free(ID **id_pt)
+static void seqclipboard_ptr_free(Main *UNUSED(bmain), ID **id_pt)
 {
        if (ID_PT) {
                BLI_assert(ID_PT->newid != NULL);
@@ -333,7 +332,7 @@ static void seqclipboard_ptr_free(ID **id_pt)
                ID_PT = NULL;
        }
 }
-static void seqclipboard_ptr_store(ID **id_pt)
+static void seqclipboard_ptr_store(Main *UNUSED(bmain), ID **id_pt)
 {
        if (ID_PT) {
                ID *id_prev = ID_PT;
@@ -383,58 +382,43 @@ static void seqclipboard_ptr_restore(Main *bmain, ID **id_pt)
                        }
                }
 
+               /* Replace with pointer to actual datablock. */
+               seqclipboard_ptr_free(bmain, id_pt);
                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)
+static void sequence_clipboard_pointers(Main *bmain, Sequence *seq, void (*callback)(Main *, ID **))
 {
-       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);
+       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);
 }
-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);
-}
-
 /* recursive versions of functions above */
 void BKE_sequencer_base_clipboard_pointers_free(ListBase *seqbase)
 {
        Sequence *seq;
        for (seq = seqbase->first; seq; seq = seq->next) {
-               BKE_sequence_clipboard_pointers_free(seq);
+               sequence_clipboard_pointers(NULL, seq, seqclipboard_ptr_free);
                BKE_sequencer_base_clipboard_pointers_free(&seq->seqbase);
        }
 }
-void BKE_sequencer_base_clipboard_pointers_store(ListBase *seqbase)
+void BKE_sequencer_base_clipboard_pointers_store(Main *bmain, ListBase *seqbase)
 {
        Sequence *seq;
        for (seq = seqbase->first; seq; seq = seq->next) {
-               BKE_sequence_clipboard_pointers_store(seq);
-               BKE_sequencer_base_clipboard_pointers_store(&seq->seqbase);
+               sequence_clipboard_pointers(bmain, seq, seqclipboard_ptr_store);
+               BKE_sequencer_base_clipboard_pointers_store(bmain, &seq->seqbase);
        }
 }
 void BKE_sequencer_base_clipboard_pointers_restore(ListBase *seqbase, Main *bmain)
 {
        Sequence *seq;
        for (seq = seqbase->first; seq; seq = seq->next) {
-               BKE_sequence_clipboard_pointers_restore(seq, bmain);
+               sequence_clipboard_pointers(bmain, seq, seqclipboard_ptr_restore);
                BKE_sequencer_base_clipboard_pointers_restore(&seq->seqbase, bmain);
        }
 }
@@ -2078,7 +2062,7 @@ void BKE_sequencer_proxy_rebuild_finish(SeqIndexBuildContext *context, bool stop
                IMB_anim_index_rebuild_finish(context->index_context, stop);
        }
 
-       seq_free_sequence_recurse(NULL, context->seq);
+       seq_free_sequence_recurse(NULL, context->seq, true);
 
        MEM_freeN(context);
 }
@@ -5505,7 +5489,7 @@ static Sequence *seq_dupli(
                struct SeqEffectHandle sh;
                sh = BKE_sequence_get_effect(seq);
                if (sh.copy)
-                       sh.copy(seq, seqn);
+                       sh.copy(seq, seqn, flag);
 
                seqn->strip->stripdata = NULL;
 
index 6144c52..612382c 100644 (file)
@@ -51,7 +51,7 @@
 #include "BKE_sequencer.h"
 #include "BKE_report.h"
 #include "BKE_sound.h"
-
+#include "BKE_library.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
@@ -3228,6 +3228,7 @@ static void seq_copy_del_sound(Scene *scene, Sequence *seq)
 
 static int sequencer_copy_exec(bContext *C, wmOperator *op)
 {
+       Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
        Editing *ed = BKE_sequencer_editing_get(scene, false);
 
@@ -3240,7 +3241,7 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op)
                return OPERATOR_CANCELLED;
        }
 
-       BKE_sequence_base_dupli_recursive(scene, scene, &nseqbase, ed->seqbasep, SEQ_DUPE_UNIQUE_NAME, 0);
+       BKE_sequence_base_dupli_recursive(scene, scene, &nseqbase, ed->seqbasep, SEQ_DUPE_UNIQUE_NAME, LIB_ID_CREATE_NO_USER_REFCOUNT);
 
        /* To make sure the copied strips have unique names between each other add
         * them temporarily to the end of the original seqbase. (bug 25932)
@@ -3265,16 +3266,14 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op)
        seqbase_clipboard_frame = scene->r.cfra;
 
        /* Need to remove anything that references the current scene */
-       {
-               Sequence *seq;
-               for (seq = seqbase_clipboard.first; seq; seq = seq->next) {
-                       seq_copy_del_sound(scene, seq);
-               }
-
-               /* duplicate pointers */
-               BKE_sequencer_base_clipboard_pointers_store(&seqbase_clipboard);
+       for (Sequence *seq = seqbase_clipboard.first; seq; seq = seq->next) {
+               seq_copy_del_sound(scene, seq);
        }
 
+       /* Replace datablock pointers with copies, to keep things working in case
+        * datablocks get deleted or another .blend file is openeded. */
+       BKE_sequencer_base_clipboard_pointers_store(bmain, &seqbase_clipboard);
+
        return OPERATOR_FINISHED;
 }
 
@@ -3306,7 +3305,12 @@ static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op))
        ED_sequencer_deselect_all(scene);
        ofs = scene->r.cfra - seqbase_clipboard_frame;
 
+       /* Copy strips, temporarily restoring pointers to actual datablocks. This
+        * must happen on the clipboard itself, so that copying does user counting
+        * on the actual datablocks. */
+       BKE_sequencer_base_clipboard_pointers_restore(&seqbase_clipboard, bmain);
        BKE_sequence_base_dupli_recursive(scene, scene, &nseqbase, &seqbase_clipboard, SEQ_DUPE_UNIQUE_NAME, 0);
+       BKE_sequencer_base_clipboard_pointers_store(bmain, &seqbase_clipboard);
 
        /* transform pasted strips before adding */
        if (ofs) {
@@ -3315,8 +3319,6 @@ static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op))
                }
        }
 
-       BKE_sequencer_base_clipboard_pointers_restore(&nseqbase, bmain);
-
        for (iseq = nseqbase.first; iseq; iseq = iseq->next) {
                BKE_sequence_sound_init(scene, iseq);
        }
@@ -3709,7 +3711,7 @@ static int sequencer_change_effect_type_exec(bContext *C, wmOperator *op)
        }
        else {
                sh = BKE_sequence_get_effect(seq);
-               sh.free(seq);
+               sh.free(seq, true);
 
                seq->type = new_type;