NLA Editor: Duplicate/Duplicate Linked
authorJoshua Leung <aligorith@gmail.com>
Mon, 28 Apr 2014 12:07:15 +0000 (00:07 +1200)
committerJoshua Leung <aligorith@gmail.com>
Mon, 28 Apr 2014 13:59:41 +0000 (01:59 +1200)
This commit changes the default strip duplication behaviour (Shift-D) so that it will
create a copy of whatever action it uses. Previously, it was very hard, if not impossible
in some cases to create a new copy of an action to start working on in the NLA.

If you want the old behaviour, you'll need to use ALt-D (Linked Duplicates).

(Note: Although the new Shift-D may not be so optimal in all cases, I've decided to go
with this version since it aligns better with the way this works for objects. Doing the
opposite for NLA would just have added to the confusion)

release/scripts/startup/bl_ui/space_nla.py
source/blender/blenkernel/BKE_nla.h
source/blender/blenkernel/intern/nla.c
source/blender/editors/space_nla/nla_edit.c
source/blender/editors/space_nla/nla_ops.c

index a07d2021243347be8f32fea1e3c65df02349c91a..ae5d308b0d30c3bdabc88de920ecfac98fc32767 100644 (file)
@@ -133,7 +133,8 @@ class NLA_MT_edit(Menu):
         layout.operator_menu_enum("nla.snap", "type", text="Snap")
 
         layout.separator()
-        layout.operator("nla.duplicate")
+        layout.operator("nla.duplicate", text="Duplicate")
+        layout.operator("nla.duplicate", text="Linked Duplicate").linked = True
         layout.operator("nla.split")
         layout.operator("nla.delete")
 
index 7823efc3baec70f596111eea53eb50240fb632a6..0c29179aa1c0f05371e467a205c9fbde939eb0b2 100644 (file)
@@ -47,8 +47,8 @@ void free_nlastrip(ListBase *strips, struct NlaStrip *strip);
 void free_nlatrack(ListBase *tracks, struct NlaTrack *nlt);
 void free_nladata(ListBase *tracks);
 
-struct NlaStrip *copy_nlastrip(struct NlaStrip *strip);
-struct NlaTrack *copy_nlatrack(struct NlaTrack *nlt);
+struct NlaStrip *copy_nlastrip(struct NlaStrip *strip, const bool use_same_action);
+struct NlaTrack *copy_nlatrack(struct NlaTrack *nlt, const bool use_same_actions);
 void copy_nladata(ListBase *dst, ListBase *src);
 
 struct NlaTrack *add_nlatrack(struct AnimData *adt, struct NlaTrack *prev);
index d251a8599b188b46fd0311d79b4318c2b93a3da1..0c244e8a40b3ad754d2cf05478ecfa433b2468c6 100644 (file)
@@ -157,8 +157,10 @@ void free_nladata(ListBase *tracks)
 
 /* Copying ------------------------------------------- */
 
-/* Copy NLA strip */
-NlaStrip *copy_nlastrip(NlaStrip *strip)
+/* Copy NLA strip 
+ * < use_same_action: if true, the existing action is used (instead of being duplicated)
+ */
+NlaStrip *copy_nlastrip(NlaStrip *strip, const bool use_same_action)
 {
        NlaStrip *strip_d;
        NlaStrip *cs, *cs_d;
@@ -171,9 +173,17 @@ NlaStrip *copy_nlastrip(NlaStrip *strip)
        strip_d = MEM_dupallocN(strip);
        strip_d->next = strip_d->prev = NULL;
        
-       /* increase user-count of action */
-       if (strip_d->act)
-               id_us_plus(&strip_d->act->id);
+       /* handle action */
+       if (strip_d->act) {
+               if (use_same_action) {
+                       /* increase user-count of action */
+                       id_us_plus(&strip_d->act->id);
+               }
+               else {
+                       /* use a copy of the action instead (user count shouldn't have changed yet) */
+                       strip_d->act = BKE_action_copy(strip_d->act);
+               }
+       }
                
        /* copy F-Curves and modifiers */
        copy_fcurves(&strip_d->fcurves, &strip->fcurves);
@@ -183,7 +193,7 @@ NlaStrip *copy_nlastrip(NlaStrip *strip)
        BLI_listbase_clear(&strip_d->strips);
        
        for (cs = strip->strips.first; cs; cs = cs->next) {
-               cs_d = copy_nlastrip(cs);
+               cs_d = copy_nlastrip(cs, use_same_action);
                BLI_addtail(&strip_d->strips, cs_d);
        }
        
@@ -192,7 +202,7 @@ NlaStrip *copy_nlastrip(NlaStrip *strip)
 }
 
 /* Copy NLA Track */
-NlaTrack *copy_nlatrack(NlaTrack *nlt)
+NlaTrack *copy_nlatrack(NlaTrack *nlt, const bool use_same_actions)
 {
        NlaStrip *strip, *strip_d;
        NlaTrack *nlt_d;
@@ -209,7 +219,7 @@ NlaTrack *copy_nlatrack(NlaTrack *nlt)
        BLI_listbase_clear(&nlt_d->strips);
        
        for (strip = nlt->strips.first; strip; strip = strip->next) {
-               strip_d = copy_nlastrip(strip);
+               strip_d = copy_nlastrip(strip, use_same_actions);
                BLI_addtail(&nlt_d->strips, strip_d);
        }
        
@@ -232,7 +242,8 @@ void copy_nladata(ListBase *dst, ListBase *src)
        /* copy each NLA-track, one at a time */
        for (nlt = src->first; nlt; nlt = nlt->next) {
                /* make a copy, and add the copy to the destination list */
-               nlt_d = copy_nlatrack(nlt);
+               // XXX: we need to fix this sometime
+               nlt_d = copy_nlatrack(nlt, true);
                BLI_addtail(dst, nlt_d);
        }
 }
index 8221fb0199b221f5de229a0ede220564f481f301..bb1e0e4245f11dc0686dc9b4fae2ae3b8379957b 100644 (file)
@@ -887,7 +887,7 @@ void NLA_OT_meta_remove(wmOperatorType *ot)
  * the originals were housed in.
  */
  
-static int nlaedit_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
+static int nlaedit_duplicate_exec(bContext *C, wmOperator *op)
 {
        bAnimContext ac;
        
@@ -895,6 +895,7 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
        bAnimListElem *ale;
        int filter;
        
+       bool linked = RNA_boolean_get(op->ptr, "linked");
        bool done = false;
        
        /* get editor data */
@@ -920,7 +921,7 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
                        /* if selected, split the strip at its midpoint */
                        if (strip->flag & NLASTRIP_FLAG_SELECT) {
                                /* make a copy (assume that this is possible) */
-                               nstrip = copy_nlastrip(strip);
+                               nstrip = copy_nlastrip(strip, linked);
                                
                                /* in case there's no space in the track above, or we haven't got a reference to it yet, try adding */
                                if (BKE_nlatrack_add_strip(nlt->next, nstrip) == 0) {
@@ -985,6 +986,9 @@ void NLA_OT_duplicate(wmOperatorType *ot)
        /* flags */
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
        
+       /* own properties */
+       ot->prop = RNA_def_boolean(ot->srna, "linked", false, "Linked", "When duplicating strips, assign new copies of the actions they use");
+       
        /* to give to transform */
        RNA_def_enum(ot->srna, "mode", transform_mode_types, TFM_TRANSLATION, "Mode", "");
 }
@@ -1102,7 +1106,7 @@ static void nlaedit_split_strip_actclip(AnimData *adt, NlaTrack *nlt, NlaStrip *
        /* make a copy (assume that this is possible) and append
         * it immediately after the current strip
         */
-       nstrip = copy_nlastrip(strip);
+       nstrip = copy_nlastrip(strip, true);
        BLI_insertlinkafter(&nlt->strips, strip, nstrip);
        
        /* set the endpoint of the first strip and the start of the new strip 
index 373879a278b82bf7644865614d236b14aab3407f..9dc598bc382018058843fe9a09cf404296c1b234 100644 (file)
@@ -256,7 +256,11 @@ static void nla_keymap_main(wmKeyConfig *keyconf, wmKeyMap *keymap)
        WM_keymap_add_item(keymap, "NLA_OT_meta_remove", GKEY, KM_PRESS, KM_ALT, 0);
                
        /* duplicate */
-       WM_keymap_add_item(keymap, "NLA_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0);
+       kmi = WM_keymap_add_item(keymap, "NLA_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0);
+       RNA_boolean_set(kmi->ptr, "linked", false);
+       
+       kmi = WM_keymap_add_item(keymap, "NLA_OT_duplicate", DKEY, KM_PRESS, KM_ALT, 0);
+       RNA_boolean_set(kmi->ptr, "linked", true);
                
        /* delete */
        WM_keymap_add_item(keymap, "NLA_OT_delete", XKEY, KM_PRESS, 0, 0);