NLA "Add Track" can now be used to add tracks to previously empty AnimData
authorJoshua Leung <aligorith@gmail.com>
Sat, 16 Mar 2013 05:09:32 +0000 (05:09 +0000)
committerJoshua Leung <aligorith@gmail.com>
Sat, 16 Mar 2013 05:09:32 +0000 (05:09 +0000)
blocks, provided the blocks in question are in fact selected.

source/blender/editors/animation/anim_filter.c
source/blender/editors/include/ED_anim_api.h
source/blender/editors/space_nla/nla_channels.c

index b3b0b09bac03f707033ab440c40794959dbde4a6..7416c559522a3a5e36a1d43cbe1e4b09717913d5 100644 (file)
@@ -1296,7 +1296,9 @@ static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDope
                ANIMDATA_FILTER_CASES(iat,
                        { /* AnimData */
                                /* specifically filter animdata block */
-                               ANIMCHANNEL_NEW_CHANNEL(adt, ANIMTYPE_ANIMDATA, id);
+                               if (ANIMCHANNEL_SELOK(SEL_ANIMDATA(adt)) ) {
+                                       ANIMCHANNEL_NEW_CHANNEL(adt, ANIMTYPE_ANIMDATA, id);
+                               }
                        },
                        { /* NLA */
                                items += animfilter_nla(ac, anim_data, ads, adt, filter_mode, id);
@@ -1346,7 +1348,9 @@ static size_t animdata_filter_shapekey(bAnimContext *ac, ListBase *anim_data, Ke
                // TODO: somehow manage to pass dopesheet info down here too?
                if (key->adt) {
                        if (filter_mode & ANIMFILTER_ANIMDATA) {
-                               ANIMCHANNEL_NEW_CHANNEL(key->adt, ANIMTYPE_ANIMDATA, key);
+                               if (ANIMCHANNEL_SELOK(SEL_ANIMDATA(key->adt)) ) {
+                                       ANIMCHANNEL_NEW_CHANNEL(key->adt, ANIMTYPE_ANIMDATA, key);
+                               }
                        }
                        else if (key->adt->action) {
                                items = animfilter_action(ac, anim_data, NULL, key->adt->action, filter_mode, (ID *)key);
index 20f568a3642ef84e21a222d222b3036d699ab169..954ea18e0ab8c9451f0ed27e69627044133a1cef 100644 (file)
@@ -292,11 +292,14 @@ typedef enum eAnimFilter_Flags {
 #define SEL_MASKLAY(masklay) (masklay->flag & SELECT)
 
 
-
 /* NLA only */
 #define SEL_NLT(nlt) (nlt->flag & NLATRACK_SELECTED)
 #define EDITABLE_NLT(nlt) ((nlt->flag & NLATRACK_PROTECTED) == 0)
 
+
+/* AnimData - NLA mostly... */
+#define SEL_ANIMDATA(adt) (adt->flag & ADT_UI_SELECTED)
+
 /* -------------- Channel Defines -------------- */
 
 /* channel heights */
index f9732a79a117ecda7d715fa2130b285e243aba6e..a4b036bf00f74098af9841277b803f6a7b87bb1f 100644 (file)
@@ -48,6 +48,7 @@
 #include "BKE_context.h"
 #include "BKE_global.h"
 #include "BKE_screen.h"
+#include "BKE_report.h"
 
 #include "ED_anim_api.h"
 #include "ED_keyframes_edit.h"
@@ -393,24 +394,18 @@ void NLA_OT_channels_click(wmOperatorType *ot)
 /* ******************** Add Tracks Operator ***************************** */
 /* Add NLA Tracks to the same AnimData block as a selected track, or above the selected tracks */
 
-static int nlaedit_add_tracks_exec(bContext *C, wmOperator *op)
+/* helper - add NLA Tracks alongside existing ones */
+static bool nlaedit_add_tracks_existing(bAnimContext *ac, bool above_sel)
 {
-       bAnimContext ac;
-       
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
        int filter;
-       
        AnimData *lastAdt = NULL;
-       short above_sel = RNA_boolean_get(op->ptr, "above_selected");
+       bool added = false;
        
-       /* get editor data */
-       if (ANIM_animdata_get_context(C, &ac) == 0)
-               return OPERATOR_CANCELLED;
-               
-       /* get a list of the AnimData blocks being shown in the NLA */
-       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL);
-       ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+       /* get a list of the (selected) NLA Tracks being shown in the NLA */
+       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
+       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* add tracks... */
        for (ale = anim_data.first; ale; ale = ale->next) {
@@ -424,11 +419,13 @@ static int nlaedit_add_tracks_exec(bContext *C, wmOperator *op)
                        if (above_sel) {
                                /* just add a new one above this one */
                                add_nlatrack(adt, nlt);
+                               added = true;
                        }
                        else if ((lastAdt == NULL) || (adt != lastAdt)) {
                                /* add one track to the top of the owning AnimData's stack, then don't add anymore to this stack */
                                add_nlatrack(adt, NULL);
                                lastAdt = adt;
+                               added = true;
                        }
                }
        }
@@ -436,17 +433,79 @@ static int nlaedit_add_tracks_exec(bContext *C, wmOperator *op)
        /* free temp data */
        BLI_freelistN(&anim_data);
        
-       /* set notifier that things have changed */
-       WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+       return added;
+}
+
+/* helper - add NLA Tracks to empty (and selected) AnimData blocks */
+static bool nlaedit_add_tracks_empty(bAnimContext *ac)
+{
+       ListBase anim_data = {NULL, NULL};
+       bAnimListElem *ale;
+       int filter;
+       bool added = false;
        
-       /* done */
-       return OPERATOR_FINISHED;
+       /* get a list of the selected AnimData blocks in the NLA */
+       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
+       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+       
+       /* check if selected AnimData blocks are empty, and add tracks if so... */
+       for (ale = anim_data.first; ale; ale = ale->next) {
+               AnimData *adt = ale->adt;
+               
+               /* sanity check */
+               BLI_assert(adt->flag & ADT_UI_SELECTED);
+               
+               /* ensure it is empty */
+               if (adt->nla_tracks.first == NULL) {
+                       /* add new track to this AnimData block then */
+                       add_nlatrack(adt, NULL);
+                       added = true;
+               }
+       }
+       
+       /* cleanup */
+       BLI_freelistN(&anim_data);
+       
+       return added;
+}
+
+/* Add Tracks exec() */
+static int nlaedit_add_tracks_exec(bContext *C, wmOperator *op)
+{
+       bAnimContext ac;
+       bool above_sel = RNA_boolean_get(op->ptr, "above_selected");
+       bool op_done = false;
+       
+       /* get editor data */
+       if (ANIM_animdata_get_context(C, &ac) == 0)
+               return OPERATOR_CANCELLED;
+               
+       /* perform adding in two passes - existing first so that we don't double up for empty */
+       op_done |= nlaedit_add_tracks_existing(&ac, above_sel);
+       op_done |= nlaedit_add_tracks_empty(&ac);
+       
+       /* done? */
+       if (op_done) {
+               /* set notifier that things have changed */
+               WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+               
+               /* done */
+               return OPERATOR_FINISHED;
+       }
+       else {
+               /* failed to add any tracks */
+               BKE_report(op->reports, RPT_WARNING,
+                          "Select an existing NLA Track or an empty action line first");
+               
+               /* not done */
+               return OPERATOR_CANCELLED;
+       }
 }
 
 void NLA_OT_tracks_add(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name = "Add Track(s)";
+       ot->name = "Add Tracks";
        ot->idname = "NLA_OT_tracks_add";
        ot->description = "Add NLA-Tracks above/after the selected tracks";