Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / animation / anim_channels_edit.c
index 59ae45e446a0eef7df671f9dd2eab80771384cbb..20e5bec44a37b188e19d4c9aed57ee5b60b59849 100644 (file)
 
 #include "MEM_guardedalloc.h"
 
+#include "BKE_depsgraph.h"
 #include "BLI_blenlib.h"
 #include "BLI_utildefines.h"
+#include "BLI_listbase.h"
 #include "BKE_library.h"
 
 #include "DNA_anim_types.h"
@@ -48,6 +50,7 @@
 #include "RNA_access.h"
 #include "RNA_define.h"
 
+#include "BKE_animsys.h"
 #include "BKE_action.h"
 #include "BKE_fcurve.h"
 #include "BKE_gpencil.h"
@@ -58,7 +61,9 @@
 #include "UI_view2d.h"
 
 #include "ED_anim_api.h"
+#include "ED_armature.h"
 #include "ED_keyframes_edit.h" // XXX move the select modes out of there!
+#include "ED_object.h"
 #include "ED_screen.h"
 
 #include "WM_api.h"
 
 /* Set the given animation-channel as the active one for the active context */
 // TODO: extend for animdata types...
-void ANIM_set_active_channel(bAnimContext *ac, void *data, short datatype, int filter, void *channel_data, short channel_type)
+void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datatype, eAnimFilter_Flags filter, void *channel_data, eAnim_ChannelType channel_type)
 {
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
        
        /* try to build list of filtered items */
        ANIM_animdata_filter(ac, &anim_data, filter, data, datatype);
-       if (anim_data.first == NULL)
+       if (BLI_listbase_is_empty(&anim_data))
                return;
                
        /* only clear the 'active' flag for the channels of the same type */
@@ -97,6 +102,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, short datatype, int f
                                break;
                        }
                        case ANIMTYPE_FCURVE:
+                       case ANIMTYPE_NLACURVE:
                        {
                                FCurve *fcu = (FCurve *)ale->data;
                                
@@ -114,10 +120,10 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, short datatype, int f
                        case ANIMTYPE_DSMAT:    /* Datablock AnimData Expanders */
                        case ANIMTYPE_DSLAM:
                        case ANIMTYPE_DSCAM:
+                       case ANIMTYPE_DSCACHEFILE:
                        case ANIMTYPE_DSCUR:
                        case ANIMTYPE_DSSKEY:
                        case ANIMTYPE_DSWOR:
-                       case ANIMTYPE_DSPART:
                        case ANIMTYPE_DSMBALL:
                        case ANIMTYPE_DSARM:
                        case ANIMTYPE_DSMESH:
@@ -125,6 +131,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, short datatype, int f
                        case ANIMTYPE_DSLAT:
                        case ANIMTYPE_DSLINESTYLE:
                        case ANIMTYPE_DSSPK:
+                       case ANIMTYPE_DSGPENCIL:
                        {
                                /* need to verify that this data is valid for now */
                                if (ale->adt) {
@@ -132,6 +139,13 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, short datatype, int f
                                }
                                break;
                        }
+                       case ANIMTYPE_GPLAYER:
+                       {
+                               bGPDlayer *gpl = (bGPDlayer *)ale->data;
+                               
+                               ACHANNEL_SET_FLAG(gpl, ACHANNEL_SETFLAG_CLEAR, GP_LAYER_ACTIVE);
+                               break;
+                       }
                }
        }
        
@@ -145,6 +159,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, short datatype, int f
                                break;
                        }
                        case ANIMTYPE_FCURVE:
+                       case ANIMTYPE_NLACURVE:
                        {
                                FCurve *fcu = (FCurve *)channel_data;
                                fcu->flag |= FCURVE_ACTIVE;
@@ -160,16 +175,19 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, short datatype, int f
                        case ANIMTYPE_DSMAT:    /* Datablock AnimData Expanders */
                        case ANIMTYPE_DSLAM:
                        case ANIMTYPE_DSCAM:
+                       case ANIMTYPE_DSCACHEFILE:
                        case ANIMTYPE_DSCUR:
                        case ANIMTYPE_DSSKEY:
                        case ANIMTYPE_DSWOR:
-                       case ANIMTYPE_DSPART:
                        case ANIMTYPE_DSMBALL:
                        case ANIMTYPE_DSARM:
                        case ANIMTYPE_DSMESH:
                        case ANIMTYPE_DSLAT:
                        case ANIMTYPE_DSLINESTYLE:
                        case ANIMTYPE_DSSPK:
+                       case ANIMTYPE_DSNTREE:
+                       case ANIMTYPE_DSTEX:
+                       case ANIMTYPE_DSGPENCIL:
                        {
                                /* need to verify that this data is valid for now */
                                if (ale && ale->adt) {
@@ -177,11 +195,28 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, short datatype, int f
                                }
                                break;
                        }
+                       
+                       case ANIMTYPE_GPLAYER:
+                       {
+                               bGPDlayer *gpl = (bGPDlayer *)channel_data;
+                               gpl->flag |= GP_LAYER_ACTIVE;
+                               break;
+                       }
+                       
+                       /* unhandled currently, but may be interesting */
+                       case ANIMTYPE_MASKLAYER:
+                       case ANIMTYPE_SHAPEKEY:
+                       case ANIMTYPE_NLAACTION:
+                               break;
+                       
+                       /* other types */
+                       default:
+                               break;
                }
        }
        
        /* clean up */
-       BLI_freelistN(&anim_data);
+       ANIM_animdata_freelist(&anim_data);
 }
 
 /* Deselect all animation channels 
@@ -190,7 +225,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, short datatype, int f
  *     - test: check if deselecting instead of selecting
  *     - sel: eAnimChannels_SetFlag;
  */
-void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, short test, short sel)
+void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types datatype, bool test, eAnimChannels_SetFlag sel)
 {
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
@@ -213,16 +248,17 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s
                                                sel = ACHANNEL_SETFLAG_CLEAR;
                                        break;
                                case ANIMTYPE_OBJECT:
-                               #if 0   /* for now, do not take object selection into account, since it gets too annoying */
+#if 0   /* for now, do not take object selection into account, since it gets too annoying */
                                        if (ale->flag & SELECT)
                                                sel = ACHANNEL_SETFLAG_CLEAR;
-                               #endif
+#endif
                                        break;
                                case ANIMTYPE_GROUP:
                                        if (ale->flag & AGRP_SELECTED)
                                                sel = ACHANNEL_SETFLAG_CLEAR;
                                        break;
                                case ANIMTYPE_FCURVE:
+                               case ANIMTYPE_NLACURVE:
                                        if (ale->flag & FCURVE_SELECTED)
                                                sel = ACHANNEL_SETFLAG_CLEAR;
                                        break;
@@ -239,10 +275,10 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s
                                case ANIMTYPE_DSMAT:    /* Datablock AnimData Expanders */
                                case ANIMTYPE_DSLAM:
                                case ANIMTYPE_DSCAM:
+                               case ANIMTYPE_DSCACHEFILE:
                                case ANIMTYPE_DSCUR:
                                case ANIMTYPE_DSSKEY:
                                case ANIMTYPE_DSWOR:
-                               case ANIMTYPE_DSPART:
                                case ANIMTYPE_DSMBALL:
                                case ANIMTYPE_DSARM:
                                case ANIMTYPE_DSMESH:
@@ -251,6 +287,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s
                                case ANIMTYPE_DSLAT:
                                case ANIMTYPE_DSLINESTYLE:
                                case ANIMTYPE_DSSPK:
+                               case ANIMTYPE_DSGPENCIL:
                                {
                                        if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED))
                                                sel = ACHANNEL_SETFLAG_CLEAR;
@@ -284,7 +321,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s
                        }
                        case ANIMTYPE_OBJECT:
                        {
-                       #if 0   /* for now, do not take object selection into account, since it gets too annoying */
+#if 0   /* for now, do not take object selection into account, since it gets too annoying */
                                Base *base = (Base *)ale->data;
                                Object *ob = base->object;
 
@@ -294,7 +331,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s
                                if (ob->adt) {
                                        ACHANNEL_SET_FLAG(ob, sel, ADT_UI_SELECTED);
                                }
-                       #endif
+#endif
                                break;
                        }
                        case ANIMTYPE_GROUP:
@@ -306,6 +343,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s
                                break;
                        }
                        case ANIMTYPE_FCURVE:
+                       case ANIMTYPE_NLACURVE:
                        {
                                FCurve *fcu = (FCurve *)ale->data;
                                
@@ -332,10 +370,10 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s
                        case ANIMTYPE_DSMAT:    /* Datablock AnimData Expanders */
                        case ANIMTYPE_DSLAM:
                        case ANIMTYPE_DSCAM:
+                       case ANIMTYPE_DSCACHEFILE:
                        case ANIMTYPE_DSCUR:
                        case ANIMTYPE_DSSKEY:
                        case ANIMTYPE_DSWOR:
-                       case ANIMTYPE_DSPART:
                        case ANIMTYPE_DSMBALL:
                        case ANIMTYPE_DSARM:
                        case ANIMTYPE_DSMESH:
@@ -344,6 +382,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s
                        case ANIMTYPE_DSLAT:
                        case ANIMTYPE_DSLINESTYLE:
                        case ANIMTYPE_DSSPK:
+                       case ANIMTYPE_DSGPENCIL:
                        {
                                /* need to verify that this data is valid for now */
                                if (ale->adt) {
@@ -370,7 +409,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s
        }
        
        /* Cleanup */
-       BLI_freelistN(&anim_data);
+       ANIM_animdata_freelist(&anim_data);
 }
 
 /* ---------------------------- Graph Editor ------------------------------------- */
@@ -384,7 +423,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s
  *     - setting: type of setting to set
  *     - on: whether the visibility setting has been enabled or disabled 
  */
-void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAnimListElem *ale_setting, int setting, short on)
+void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAnimListElem *ale_setting, eAnimChannel_Settings setting, eAnimChannels_SetFlag mode)
 {
        bAnimListElem *ale, *match = NULL;
        int prevLevel = 0, matchLevel = 0;
@@ -410,7 +449,7 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn
                return;
        }
        else {
-               bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale_setting);
+               const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale_setting);
                
                if (acf == NULL) {
                        printf("ERROR: no channel info for the changed channel\n");
@@ -434,12 +473,12 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn
         *      - only flush up if the current state is now disabled (negative 'off' state is default)
         *        (otherwise, it's too much work to force the parents to be active too)
         */
-       if ( ((setting == ACHANNEL_SETTING_VISIBLE) && on) ||
-            ((setting != ACHANNEL_SETTING_VISIBLE) && on == 0) )
+       if ( ((setting == ACHANNEL_SETTING_VISIBLE) && (mode != ACHANNEL_SETFLAG_CLEAR)) ||
+            ((setting != ACHANNEL_SETTING_VISIBLE) && (mode == ACHANNEL_SETFLAG_CLEAR)))
        {
                /* go backwards in the list, until the highest-ranking element (by indention has been covered) */
                for (ale = match->prev; ale; ale = ale->prev) {
-                       bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+                       const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
                        int level;
                        
                        /* if no channel info was found, skip, since this type might not have any useful info */
@@ -458,7 +497,7 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn
                         */
                        if (level < prevLevel) {
                                /* flush the new status... */
-                               ANIM_channel_setting_set(ac, ale, setting, on);
+                               ANIM_channel_setting_set(ac, ale, setting, mode);
                                
                                /* store this level as the 'old' level now */
                                prevLevel = level;
@@ -483,7 +522,7 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn
        {
                /* go forwards in the list, until the lowest-ranking element (by indention has been covered) */
                for (ale = match->next; ale; ale = ale->next) {
-                       bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
+                       const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
                        int level;
                        
                        /* if no channel info was found, skip, since this type might not have any useful info */
@@ -499,7 +538,7 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn
                         * flush the new status...
                         */
                        if (level > matchLevel)
-                               ANIM_channel_setting_set(ac, ale, setting, on);
+                               ANIM_channel_setting_set(ac, ale, setting, mode);
                        /* however, if the level is 'less than or equal to' the channel that was changed,
                         * (i.e. the current channel is as important if not more important than the changed channel)
                         * then we should stop, since we've found the last one of the children we should flush
@@ -548,7 +587,7 @@ void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, AnimData *adt, FCurve *f
                        /* if group has no more channels, remove it too, 
                         * otherwise can have many dangling groups [#33541]
                         */
-                       if (agrp->channels.first == NULL) {
+                       if (BLI_listbase_is_empty(&agrp->channels)) {
                                BLI_freelinkN(&act->groups, agrp);
                        }
                }
@@ -563,7 +602,7 @@ void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, AnimData *adt, FCurve *f
                 * channel list that are empty, and linger around long after the data they
                 * are for has disappeared (and probably won't come back).
                 */
-               if ((act->curves.first == NULL) && (adt->flag & ADT_NLA_EDIT_ON) == 0) {
+               if (BLI_listbase_is_empty(&act->curves) && (adt->flag & ADT_NLA_EDIT_ON) == 0) {
                        id_us_min(&act->id);
                        adt->action = NULL;
                }
@@ -588,7 +627,7 @@ static int animedit_poll_channels_active(bContext *C)
        if (ELEM(NULL, sa, CTX_wm_region(C)))
                return 0;
        /* animation editor test */
-       if (ELEM3(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0)
+       if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0)
                return 0;
 
        return 1;
@@ -605,7 +644,7 @@ static int animedit_poll_channels_nla_tweakmode_off(bContext *C)
        if (ELEM(NULL, sa, CTX_wm_region(C)))
                return 0;
        /* animation editor test */
-       if (ELEM3(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0)
+       if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0)
                return 0;
        
        /* NLA TweakMode test */
@@ -620,13 +659,13 @@ static int animedit_poll_channels_nla_tweakmode_off(bContext *C)
 /* ****************** Rearrange Channels Operator ******************* */
 
 /* constants for channel rearranging */
-/* WARNING: don't change exising ones without modifying rearrange func accordingly */
-enum {
+/* WARNING: don't change existing ones without modifying rearrange func accordingly */
+typedef enum eRearrangeAnimChan_Mode {
        REARRANGE_ANIMCHAN_TOP = -2,
        REARRANGE_ANIMCHAN_UP = -1,
        REARRANGE_ANIMCHAN_DOWN = 1,
        REARRANGE_ANIMCHAN_BOTTOM = 2
-};
+} eRearrangeAnimChan_Mode;
 
 /* defines for rearranging channels */
 static EnumPropertyItem prop_animchannel_rearrange_types[] = {
@@ -651,13 +690,14 @@ typedef struct tReorderChannelIsland {
 typedef enum eReorderIslandFlag {
        REORDER_ISLAND_SELECTED         = (1 << 0),   /* island is selected */
        REORDER_ISLAND_UNTOUCHABLE      = (1 << 1),   /* island should be ignored */
-       REORDER_ISLAND_MOVED            = (1 << 2)    /* island has already been moved */
+       REORDER_ISLAND_MOVED            = (1 << 2),   /* island has already been moved */
+       REORDER_ISLAND_HIDDEN           = (1 << 3),   /* island is not visible */
 } eReorderIslandFlag;
 
 
 /* Rearrange Methods --------------------------------------------- */
 
-static short rearrange_island_ok(tReorderChannelIsland *island)
+static bool rearrange_island_ok(tReorderChannelIsland *island)
 {
        /* island must not be untouchable */
        if (island->flag & REORDER_ISLAND_UNTOUCHABLE)
@@ -669,7 +709,7 @@ static short rearrange_island_ok(tReorderChannelIsland *island)
 
 /* ............................. */
 
-static short rearrange_island_top(ListBase *list, tReorderChannelIsland *island)
+static bool rearrange_island_top(ListBase *list, tReorderChannelIsland *island)
 {
        if (rearrange_island_ok(island)) {
                /* remove from current position */
@@ -684,12 +724,17 @@ static short rearrange_island_top(ListBase *list, tReorderChannelIsland *island)
        return 0;
 }
 
-static short rearrange_island_up(ListBase *list, tReorderChannelIsland *island)
+static bool rearrange_island_up(ListBase *list, tReorderChannelIsland *island)
 {
        if (rearrange_island_ok(island)) {
                /* moving up = moving before the previous island, otherwise we're in the same place */
                tReorderChannelIsland *prev = island->prev;
-               
+
+               /* Skip hidden islands! */
+               while (prev && prev->flag & REORDER_ISLAND_HIDDEN) {
+                       prev = prev->prev;
+               }
+
                if (prev) {
                        /* remove from current position */
                        BLI_remlink(list, island);
@@ -704,12 +749,17 @@ static short rearrange_island_up(ListBase *list, tReorderChannelIsland *island)
        return 0;
 }
 
-static short rearrange_island_down(ListBase *list, tReorderChannelIsland *island)
+static bool rearrange_island_down(ListBase *list, tReorderChannelIsland *island)
 {
        if (rearrange_island_ok(island)) {
                /* moving down = moving after the next island, otherwise we're in the same place */
                tReorderChannelIsland *next = island->next;
-               
+
+               /* Skip hidden islands! */
+               while (next && next->flag & REORDER_ISLAND_HIDDEN) {
+                       next = next->next;
+               }
+
                if (next) {
                        /* can only move past if next is not untouchable (i.e. nothing can go after it) */
                        if ((next->flag & REORDER_ISLAND_UNTOUCHABLE) == 0) {
@@ -719,16 +769,16 @@ static short rearrange_island_down(ListBase *list, tReorderChannelIsland *island
                                /* push it down */
                                BLI_insertlinkafter(list, next, island);
                                
-                               return 1;
+                               return true;
                        }
                }
                /* else: no next channel, so we're at the bottom already, so can't move */
        }
        
-       return 0;
+       return false;
 }
 
-static short rearrange_island_bottom(ListBase *list, tReorderChannelIsland *island)
+static bool rearrange_island_bottom(ListBase *list, tReorderChannelIsland *island)
 {
        if (rearrange_island_ok(island)) {
                tReorderChannelIsland *last = list->last;
@@ -747,23 +797,25 @@ static short rearrange_island_bottom(ListBase *list, tReorderChannelIsland *isla
                        
                }
                
-               return 1;
+               return true;
        }
        
-       return 0;
+       return false;
 }
 
 /* ............................. */
 
-/* typedef for channel rearranging function 
- * < list: list that channels belong to
- * < island: island to be moved
- * > return[0]: whether operation was a success
+/**
+ * typedef for channel rearranging function
+ *
+ * \param list List of tReorderChannelIsland's that channels belong to
+ * \param island Island to be moved
+ * \return Whether operation was a success
  */
-typedef short (*AnimChanRearrangeFp)(ListBase *list, tReorderChannelIsland *island);
+typedef bool (*AnimChanRearrangeFp)(ListBase *list, tReorderChannelIsland *island);
 
 /* get rearranging function, given 'rearrange' mode */
-static AnimChanRearrangeFp rearrange_get_mode_func(short mode)
+static AnimChanRearrangeFp rearrange_get_mode_func(eRearrangeAnimChan_Mode mode)
 {
        switch (mode) {
                case REARRANGE_ANIMCHAN_TOP:
@@ -782,10 +834,12 @@ static AnimChanRearrangeFp rearrange_get_mode_func(short mode)
 /* Rearrange Islands Generics ------------------------------------- */
 
 /* add channel into list of islands */
-static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *srcList, Link *channel, short type)
+static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *srcList,
+                                                 Link *channel, eAnim_ChannelType type,
+                                                 const bool is_hidden)
 {
        tReorderChannelIsland *island = islands->last;  /* always try to add to last island if possible */
-       short is_sel = 0, is_untouchable = 0;
+       bool is_sel = false, is_untouchable = false;
        
        /* get flags - selected and untouchable from the channel */
        switch (type) {
@@ -798,6 +852,7 @@ static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *sr
                        break;
                }
                case ANIMTYPE_FCURVE:
+               case ANIMTYPE_NLACURVE:
                {
                        FCurve *fcu = (FCurve *)channel;
                        
@@ -811,15 +866,28 @@ static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *sr
                        is_sel = SEL_NLT(nlt);
                        break;
                }
+               case ANIMTYPE_GPLAYER:
+               {
+                       bGPDlayer *gpl = (bGPDlayer *)channel;
+                       
+                       is_sel = SEL_GPL(gpl);
+                       break;
+               }
                default:
-                       printf("rearrange_animchannel_add_to_islands(): don't know how to handle channels of type %d\n", type);
+                       printf("rearrange_animchannel_add_to_islands(): don't know how to handle channels of type %u\n", type);
                        return;
        }
        
        /* do we need to add to a new island? */
-       if ((island == NULL) ||                                 /* 1) no islands yet */
-           ((island->flag & REORDER_ISLAND_SELECTED) == 0) ||  /* 2) unselected islands have single channels only - to allow up/down movement */
-           (is_sel == 0))                                      /* 3) if channel is unselected, stop existing island (it was either wrong sel status, or full already) */
+       if (/* 1) no islands yet */
+           (island == NULL) ||
+           /* 2) unselected islands have single channels only - to allow up/down movement */
+           ((island->flag & REORDER_ISLAND_SELECTED) == 0) ||
+           /* 3) if channel is unselected, stop existing island (it was either wrong sel status, or full already) */
+           (is_sel == 0) ||
+           /* 4) hidden status changes */
+           ((island->flag & REORDER_ISLAND_HIDDEN) != is_hidden)
+           )
        {
                /* create a new island now */
                island = MEM_callocN(sizeof(tReorderChannelIsland), "tReorderChannelIsland");
@@ -829,6 +897,8 @@ static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *sr
                        island->flag |= REORDER_ISLAND_SELECTED;
                if (is_untouchable)
                        island->flag |= REORDER_ISLAND_UNTOUCHABLE;
+               if (is_hidden)
+                       island->flag |= REORDER_ISLAND_HIDDEN;
        }
 
        /* add channel to island - need to remove it from its existing list first though */
@@ -842,7 +912,7 @@ static void rearrange_animchannel_flatten_islands(ListBase *islands, ListBase *s
        tReorderChannelIsland *island, *isn = NULL;
        
        /* make sure srcList is empty now */
-       BLI_assert(srcList->first == NULL);
+       BLI_assert(BLI_listbase_is_empty(srcList));
        
        /* go through merging islands */
        for (island = islands->first; island; island = isn) {
@@ -856,21 +926,48 @@ static void rearrange_animchannel_flatten_islands(ListBase *islands, ListBase *s
 
 /* ............................. */
 
+/* get a list of all bAnimListElem's of a certain type which are currently visible */
+static void rearrange_animchannels_filter_visible(ListBase *anim_data_visible, bAnimContext *ac, eAnim_ChannelType type)
+{
+       ListBase anim_data = {NULL, NULL};
+       bAnimListElem *ale, *ale_next;
+       int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+       
+       /* get all visible channels */
+       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+       
+       /* now, only keep the ones that are of the types we are interested in */
+       for (ale = anim_data.first; ale; ale = ale_next) {
+               ale_next = ale->next;
+               
+               if (ale->type != type) {
+                       BLI_freelinkN(&anim_data, ale);
+               }
+       }
+       
+       /* return cleaned up list */
+       *anim_data_visible = anim_data;
+}
+
 /* performing rearranging of channels using islands */
-static short rearrange_animchannel_islands(ListBase *list, AnimChanRearrangeFp rearrange_func, short mode, short type)
+static bool rearrange_animchannel_islands(ListBase *list, AnimChanRearrangeFp rearrange_func,
+                                          eRearrangeAnimChan_Mode mode, eAnim_ChannelType type,
+                                          ListBase *anim_data_visible)
 {
        ListBase islands = {NULL, NULL};
        Link *channel, *chanNext = NULL;
-       short done = FALSE;
+       bool done = false;
        
        /* don't waste effort on an empty list */
-       if (list->first == NULL)
+       if (BLI_listbase_is_empty(list))
                return 0;
        
        /* group channels into islands */
        for (channel = list->first; channel; channel = chanNext) {
+               /* find out whether this channel is present in anim_data_visible or not! */
+               const bool is_hidden = (BLI_findptr(anim_data_visible, channel, offsetof(bAnimListElem, data)) == NULL);
                chanNext = channel->next;
-               rearrange_animchannel_add_to_islands(&islands, list, channel, type);
+               rearrange_animchannel_add_to_islands(&islands, list, channel, type, is_hidden);
        }
        
        /* perform moving of selected islands now, but only if there is more than one of 'em so that something will happen 
@@ -887,7 +984,7 @@ static short rearrange_animchannel_islands(ListBase *list, AnimChanRearrangeFp r
                        /* perform rearranging */
                        if (rearrange_func(&islands, island)) {
                                island->flag |= REORDER_ISLAND_MOVED;
-                               done = TRUE;
+                               done = true;
                        }
                }
        }
@@ -905,9 +1002,10 @@ static short rearrange_animchannel_islands(ListBase *list, AnimChanRearrangeFp r
  * ! NLA tracks are displayed in opposite order, so directions need care
  *     mode: REARRANGE_ANIMCHAN_*  
  */
-static void rearrange_nla_channels(bAnimContext *UNUSED(ac), AnimData *adt, short mode)
+static void rearrange_nla_channels(bAnimContext *ac, AnimData *adt, eRearrangeAnimChan_Mode mode)
 {
        AnimChanRearrangeFp rearrange_func;
+       ListBase anim_data_visible = {NULL, NULL};
        
        /* hack: invert mode so that functions will work in right order */
        mode *= -1;
@@ -917,12 +1015,14 @@ static void rearrange_nla_channels(bAnimContext *UNUSED(ac), AnimData *adt, shor
        if (rearrange_func == NULL)
                return;
        
-       /* only consider NLA data if it's accessible */
-       //if (EXPANDED_DRVD(adt) == 0)
-       //      return;
+       /* Filter visible data. */
+       rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_NLATRACK);
        
        /* perform rearranging on tracks list */
-       rearrange_animchannel_islands(&adt->nla_tracks, rearrange_func, mode, ANIMTYPE_NLATRACK);
+       rearrange_animchannel_islands(&adt->nla_tracks, rearrange_func, mode, ANIMTYPE_NLATRACK, &anim_data_visible);
+       
+       /* free temp data */
+       BLI_freelistN(&anim_data_visible);
 }
 
 /* Drivers Specific Stuff ------------------------------------------------- */
@@ -930,10 +1030,11 @@ static void rearrange_nla_channels(bAnimContext *UNUSED(ac), AnimData *adt, shor
 /* Change the order drivers within AnimData block
  *     mode: REARRANGE_ANIMCHAN_*  
  */
-static void rearrange_driver_channels(bAnimContext *UNUSED(ac), AnimData *adt, short mode)
+static void rearrange_driver_channels(bAnimContext *ac, AnimData *adt, eRearrangeAnimChan_Mode mode)
 {
        /* get rearranging function */
        AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
+       ListBase anim_data_visible = {NULL, NULL};
        
        if (rearrange_func == NULL)
                return;
@@ -942,8 +1043,14 @@ static void rearrange_driver_channels(bAnimContext *UNUSED(ac), AnimData *adt, s
        if (EXPANDED_DRVD(adt) == 0)
                return;
        
+       /* Filter visible data. */
+       rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_FCURVE);
+       
        /* perform rearranging on drivers list (drivers are really just F-Curves) */
-       rearrange_animchannel_islands(&adt->drivers, rearrange_func, mode, ANIMTYPE_FCURVE);
+       rearrange_animchannel_islands(&adt->drivers, rearrange_func, mode, ANIMTYPE_FCURVE, &anim_data_visible);
+       
+       /* free temp data */
+       BLI_freelistN(&anim_data_visible);
 }
 
 /* Action Specific Stuff ------------------------------------------------- */
@@ -989,6 +1096,13 @@ static void split_groups_action_temp(bAction *act, bActionGroup *tgrp)
                fcu->next = NULL;
                tgrp->channels.last = fcu;
                act->curves.last = NULL;
+               
+               /* ensure that all of these get their group set to this temp group 
+                * (so that visibility filtering works)
+                */
+               for (fcu = tgrp->channels.first; fcu; fcu = fcu->next) {
+                       fcu->grp = tgrp;
+               }
        }
        
        /* Add temp-group to list */
@@ -1011,8 +1125,17 @@ static void join_groups_action_temp(bAction *act)
                /* clear moved flag */
                agrp->flag &= ~AGRP_MOVED;
                
-               /* if temp-group... remove from list (but don't free as it's on the stack!) */
+               /* if group was temporary one:
+                * - unassign all FCurves which were temporarily added to it
+                * - remove from list (but don't free as it's on the stack!)
+                */
                if (agrp->flag & AGRP_TEMP) {
+                       FCurve *fcu;
+                       
+                       for (fcu = agrp->channels.first; fcu; fcu = fcu->next) {
+                               fcu->grp = NULL;
+                       }
+                       
                        BLI_remlink(&act->groups, agrp);
                        break;
                }
@@ -1022,10 +1145,11 @@ static void join_groups_action_temp(bAction *act)
 /* Change the order of anim-channels within action 
  *     mode: REARRANGE_ANIMCHAN_*  
  */
-static void rearrange_action_channels(bAnimContext *ac, bAction *act, short mode)
+static void rearrange_action_channels(bAnimContext *ac, bAction *act, eRearrangeAnimChan_Mode mode)
 {
        bActionGroup tgrp;
-       short do_channels;
+       ListBase anim_data_visible = {NULL, NULL};
+       bool do_channels;
        
        /* get rearranging function */
        AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
@@ -1036,21 +1160,35 @@ static void rearrange_action_channels(bAnimContext *ac, bAction *act, short mode
        /* make sure we're only operating with groups (vs a mixture of groups+curves) */
        split_groups_action_temp(act, &tgrp);
        
+       /* Filter visible data. */
+       rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_GROUP);
+       
        /* rearrange groups first 
         *      - the group's channels will only get considered if nothing happened when rearranging the groups
         *        i.e. the rearrange function returned 0
         */
-       do_channels = rearrange_animchannel_islands(&act->groups, rearrange_func, mode, ANIMTYPE_GROUP) == 0;
+       do_channels = (rearrange_animchannel_islands(&act->groups, rearrange_func, mode, ANIMTYPE_GROUP,
+                                                    &anim_data_visible) == 0);
+       
+       /* free temp data */
+       BLI_freelistN(&anim_data_visible);
        
        if (do_channels) {
                bActionGroup *agrp;
                
+               /* Filter visible data. */
+               rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_FCURVE);
+               
                for (agrp = act->groups.first; agrp; agrp = agrp->next) {
                        /* only consider F-Curves if they're visible (group expanded) */
                        if (EXPANDED_AGRP(ac, agrp)) {
-                               rearrange_animchannel_islands(&agrp->channels, rearrange_func, mode, ANIMTYPE_FCURVE);
+                               rearrange_animchannel_islands(&agrp->channels, rearrange_func, mode, ANIMTYPE_FCURVE,
+                                                             &anim_data_visible);
                        }
                }
+               
+               /* free temp data */
+               BLI_freelistN(&anim_data_visible);
        }
        
        /* assemble lists into one list (and clear moved tags) */
@@ -1059,10 +1197,85 @@ static void rearrange_action_channels(bAnimContext *ac, bAction *act, short mode
 
 /* ------------------- */
 
+static void rearrange_nla_control_channels(bAnimContext *ac, AnimData *adt, eRearrangeAnimChan_Mode mode)
+{
+       ListBase anim_data_visible = {NULL, NULL};
+       
+       NlaTrack *nlt;
+       NlaStrip *strip;
+       
+       /* get rearranging function */
+       AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
+       
+       if (rearrange_func == NULL)
+               return;
+               
+       /* skip if these curves aren't being shown */
+       if (adt->flag & ADT_NLA_SKEYS_COLLAPSED)
+               return;
+       
+       /* Filter visible data. */
+       rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_NLACURVE);
+       
+       /* we cannot rearrange between strips, but within each strip, we can rearrange those curves */
+       for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
+               for (strip = nlt->strips.first; strip; strip = strip->next) {
+                       rearrange_animchannel_islands(&strip->fcurves, rearrange_func, mode, ANIMTYPE_NLACURVE,
+                                                         &anim_data_visible);
+               }
+       }
+       
+       /* free temp data */
+       BLI_freelistN(&anim_data_visible);
+}
+
+/* ------------------- */
+
+static void rearrange_gpencil_channels(bAnimContext *ac, eRearrangeAnimChan_Mode mode)
+{
+       ListBase anim_data = {NULL, NULL};
+       bAnimListElem *ale;
+       int filter;
+       
+       /* get rearranging function */
+       AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
+       
+       if (rearrange_func == NULL)
+               return;
+       
+       /* get Grease Pencil datablocks */
+       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA);
+       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+       
+       for (ale = anim_data.first; ale; ale = ale->next) {
+               ListBase anim_data_visible = {NULL, NULL};
+               bGPdata *gpd = ale->data;
+               
+               /* only consider layers if this datablock is open */
+               BLI_assert(ale->type == ANIMTYPE_GPDATABLOCK);
+               if ((gpd->flag & GP_DATA_EXPAND) == 0)
+                       continue;
+               
+               /* Filter visible data. */
+               rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_GPLAYER);
+               
+               /* rearrange datablock's layers */
+               rearrange_animchannel_islands(&gpd->layers, rearrange_func, mode, ANIMTYPE_GPLAYER, &anim_data_visible);
+               
+               /* free visible layers data */
+               BLI_freelistN(&anim_data_visible);
+       }
+       
+       /* free GPD channel data */
+       ANIM_animdata_freelist(&anim_data);
+}
+
+/* ------------------- */
+
 static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
 {
        bAnimContext ac;
-       short mode;
+       eRearrangeAnimChan_Mode mode;
        
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -1074,7 +1287,7 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
        /* method to move channels depends on the editor */
        if (ac.datatype == ANIMCONT_GPENCIL) {
                /* Grease Pencil channels */
-               printf("Grease Pencil not supported for moving yet\n");
+               rearrange_gpencil_channels(&ac, mode);
        }
        else if (ac.datatype == ANIMCONT_MASK) {
                /* Grease Pencil channels */
@@ -1105,19 +1318,34 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
                                        rearrange_driver_channels(&ac, adt, mode);
                                        break;
                                
+                               case ANIMCONT_ACTION: /* Single Action only... */
                                case ANIMCONT_SHAPEKEY: // DOUBLE CHECK ME...
+                               {
+                                       if (adt->action)
+                                               rearrange_action_channels(&ac, adt->action, mode);
+                                       else if (G.debug & G_DEBUG)
+                                               printf("Animdata has no action\n");
+                                       break;
+                               }
+                               
+                               default: /* DopeSheet/Graph Editor - Some Actions + NLA Control Curves */
+                               {
+                                       /* NLA Control Curves */
+                                       if (adt->nla_tracks.first)
+                                               rearrange_nla_control_channels(&ac, adt, mode);
                                        
-                               default: /* some collection of actions */
+                                       /* Action */
                                        if (adt->action)
                                                rearrange_action_channels(&ac, adt->action, mode);
                                        else if (G.debug & G_DEBUG)
                                                printf("Animdata has no action\n");
                                        break;
+                               }
                        }
                }
                
                /* free temp data */
-               BLI_freelistN(&anim_data);
+               ANIM_animdata_freelist(&anim_data);
        }
        
        /* send notifier that things have changed */
@@ -1168,9 +1396,9 @@ static int animchannels_grouping_poll(bContext *C)
                        /* dopesheet and action only - all others are for other datatypes or have no groups */
                        if (ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_DOPESHEET) == 0)
                                return 0;
-               }
+
                        break;
-                       
+               }
                case SPACE_IPO:
                {
                        SpaceIpo *sipo = (SpaceIpo *)sl;
@@ -1178,9 +1406,9 @@ static int animchannels_grouping_poll(bContext *C)
                        /* drivers can't have groups... */
                        if (sipo->mode != SIPO_MODE_ANIMATION)
                                return 0;
-               }
+
                        break;
-                       
+               }
                /* unsupported... */
                default:
                        return 0;
@@ -1220,7 +1448,7 @@ static void animchannels_group_channels(bAnimContext *ac, bAnimListElem *adt_ref
                                /* remove F-Curve from group, then group too if it is now empty */
                                action_groups_remove_channel(act, fcu);
                                
-                               if ((grp) && (grp->channels.first == NULL)) {
+                               if ((grp) && BLI_listbase_is_empty(&grp->channels)) {
                                        BLI_freelinkN(&act->groups, grp);
                                }
                                
@@ -1230,7 +1458,7 @@ static void animchannels_group_channels(bAnimContext *ac, bAnimListElem *adt_ref
                }
                
                /* cleanup */
-               BLI_freelistN(&anim_data);
+               ANIM_animdata_freelist(&anim_data);
        }
 }
 
@@ -1261,7 +1489,7 @@ static int animchannels_group_exec(bContext *C, wmOperator *op)
                }
                
                /* free temp data */
-               BLI_freelistN(&anim_data);
+               ANIM_animdata_freelist(&anim_data);
                
                /* updatss */
                WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
@@ -1325,7 +1553,7 @@ static int animchannels_ungroup_exec(bContext *C, wmOperator *UNUSED(op))
                                BLI_addtail(&act->curves, fcu);
                                
                                /* delete group if it is now empty */
-                               if (agrp->channels.first == NULL) {
+                               if (BLI_listbase_is_empty(&agrp->channels)) {
                                        BLI_freelinkN(&act->groups, agrp);
                                }
                        }
@@ -1333,7 +1561,7 @@ static int animchannels_ungroup_exec(bContext *C, wmOperator *UNUSED(op))
        }
        
        /* cleanup */
-       BLI_freelistN(&anim_data);
+       ANIM_animdata_freelist(&anim_data);
        
        /* updates */
        WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
@@ -1410,7 +1638,7 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
                }
                
                /* cleanup */
-               BLI_freelistN(&anim_data);
+               ANIM_animdata_freelist(&anim_data);
        }
        
        /* filter data */
@@ -1430,6 +1658,27 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
                                ANIM_fcurve_delete_from_animdata(&ac, adt, fcu);
                                break;
                        }
+                       case ANIMTYPE_NLACURVE:
+                       {
+                               /* NLA Control Curve - Deleting it should disable the corresponding setting... */
+                               NlaStrip *strip = (NlaStrip *)ale->owner;
+                               FCurve *fcu = (FCurve *)ale->data;
+                               
+                               if (STREQ(fcu->rna_path, "strip_time")) {
+                                       strip->flag &= ~NLASTRIP_FLAG_USR_TIME;
+                               }
+                               else if (STREQ(fcu->rna_path, "influence")) {
+                                       strip->flag &= ~NLASTRIP_FLAG_USR_INFLUENCE;
+                               }
+                               else {
+                                       printf("ERROR: Trying to delete NLA Control Curve for unknown property '%s'\n", fcu->rna_path);
+                               }
+                               
+                               /* unlink and free the F-Curve */
+                               BLI_remlink(&strip->fcurves, fcu);
+                               free_fcurve(fcu);
+                               break;
+                       }
                        case ANIMTYPE_GPLAYER:
                        {
                                /* Grease Pencil layer */
@@ -1437,7 +1686,7 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
                                bGPDlayer *gpl = (bGPDlayer *)ale->data;
                                
                                /* try to delete the layer's data and the layer itself */
-                               free_gpencil_frames(gpl);
+                               BKE_gpencil_free_frames(gpl);
                                BLI_freelinkN(&gpd->layers, gpl);
                                break;
                        }
@@ -1455,11 +1704,12 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
        }
        
        /* cleanup */
-       BLI_freelistN(&anim_data);
+       ANIM_animdata_freelist(&anim_data);
        
        /* send notifier that things have changed */
        WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
-       
+       DAG_relations_tag_update(CTX_data_main(C));
+
        return OPERATOR_FINISHED;
 }
  
@@ -1478,175 +1728,6 @@ static void ANIM_OT_channels_delete(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
-/* ******************** Set Channel Visibility Operator *********************** */
-/* NOTE: this operator is only valid in the Graph Editor channels region */
-
-static int animchannels_visibility_set_exec(bContext *C, wmOperator *UNUSED(op))
-{
-       bAnimContext ac;
-       ListBase anim_data = {NULL, NULL};
-       ListBase all_data = {NULL, NULL};
-       bAnimListElem *ale;
-       int filter;
-       
-       /* get editor data */
-       if (ANIM_animdata_get_context(C, &ac) == 0)
-               return OPERATOR_CANCELLED;
-       
-       /* get list of all channels that selection may need to be flushed to 
-        * - hierarchy mustn't affect what we have access to here...
-        */
-       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
-       ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
-               
-       /* hide all channels not selected
-        * - hierarchy matters if we're doing this from the channels region
-        *   since we only want to apply this to channels we can "see", 
-        *   and have these affect their relatives
-        * - but for Graph Editor, this gets used also from main region
-        *   where hierarchy doesn't apply, as for [#21276]
-        */
-       if ((ac.spacetype == SPACE_IPO) && (ac.regiontype != RGN_TYPE_CHANNELS)) {
-               /* graph editor (case 2) */
-               filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_UNSEL | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
-       }
-       else {
-               /* standard case */
-               filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_UNSEL | ANIMFILTER_NODUPLIS);
-       }
-       ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-       
-       for (ale = anim_data.first; ale; ale = ale->next) {
-               /* clear setting first */
-               ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR);
-               
-               /* now also flush selection status as appropriate 
-                * NOTE: in some cases, this may result in repeat flushing being performed
-                */
-               ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, 0);
-       }
-       
-       BLI_freelistN(&anim_data);
-       
-       /* make all the selected channels visible */
-       filter = (ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
-       ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
-       for (ale = anim_data.first; ale; ale = ale->next) {
-               /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
-               /* TODO: find out why this is the case, and fix that */
-               if (ale->type == ANIMTYPE_OBJECT)
-                       continue;
-               
-               /* enable the setting */
-               ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
-               
-               /* now, also flush selection status up/down as appropriate */
-               ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, 1);
-       }
-       
-       BLI_freelistN(&anim_data);
-       BLI_freelistN(&all_data);
-       
-       
-       /* send notifier that things have changed */
-       WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
-       
-       return OPERATOR_FINISHED;
-}
-
-static void ANIM_OT_channels_visibility_set(wmOperatorType *ot)
-{
-       /* identifiers */
-       ot->name = "Set Visibility";
-       ot->idname = "ANIM_OT_channels_visibility_set";
-       ot->description = "Make only the selected animation channels visible in the Graph Editor";
-       
-       /* api callbacks */
-       ot->exec = animchannels_visibility_set_exec;
-       ot->poll = ED_operator_graphedit_active;
-       
-       /* flags */
-       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-
-/* ******************** Toggle Channel Visibility Operator *********************** */
-/* NOTE: this operator is only valid in the Graph Editor channels region */
-
-static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *UNUSED(op))
-{
-       bAnimContext ac;
-       ListBase anim_data = {NULL, NULL};
-       ListBase all_data = {NULL, NULL};
-       bAnimListElem *ale;
-       int filter;
-       short vis = ACHANNEL_SETFLAG_ADD;
-       
-       /* get editor data */
-       if (ANIM_animdata_get_context(C, &ac) == 0)
-               return OPERATOR_CANCELLED;
-               
-       /* get list of all channels that selection may need to be flushed to 
-        * - hierarchy mustn't affect what we have access to here...
-        */
-       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
-       ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
-               
-       /* filter data
-        * - restrict this to only applying on settings we can get to in the list
-        */
-       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
-       ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-       
-       /* See if we should be making showing all selected or hiding */
-       for (ale = anim_data.first; ale; ale = ale->next) {
-               /* set the setting in the appropriate way (if available) */
-               if (ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_VISIBLE)) {
-                       vis = ACHANNEL_SETFLAG_CLEAR;
-                       break;
-               }
-       }
-
-       /* Now set the flags */
-       for (ale = anim_data.first; ale; ale = ale->next) {
-               /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
-               /* TODO: find out why this is the case, and fix that */
-               if (ale->type == ANIMTYPE_OBJECT)
-                       continue;
-               
-               /* change the setting */
-               ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, vis);
-               
-               /* now, also flush selection status up/down as appropriate */
-               ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, (vis == ACHANNEL_SETFLAG_ADD));
-       }
-       
-       /* cleanup */
-       BLI_freelistN(&anim_data);
-       BLI_freelistN(&all_data);
-       
-       /* send notifier that things have changed */
-       WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
-       
-       return OPERATOR_FINISHED;
-}
-
-static void ANIM_OT_channels_visibility_toggle(wmOperatorType *ot)
-{
-       /* identifiers */
-       ot->name = "Toggle Visibility";
-       ot->idname = "ANIM_OT_channels_visibility_toggle";
-       ot->description = "Toggle visibility in Graph Editor of all selected animation channels";
-       
-       /* api callbacks */
-       ot->exec = animchannels_visibility_toggle_exec;
-       ot->poll = ED_operator_graphedit_active;
-       
-       /* flags */
-       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
 /* ********************** Set Flags Operator *********************** */
 
 /* defines for setting animation-channel flags */
@@ -1675,7 +1756,7 @@ static EnumPropertyItem prop_animchannel_settings_types[] = {
  *     onlysel: only selected channels get the flag set
  */
 // TODO: enable a setting which turns flushing on/off?
-static void setflag_anim_channels(bAnimContext *ac, short setting, short mode, short onlysel, short flush)
+static void setflag_anim_channels(bAnimContext *ac, eAnimChannel_Settings setting, eAnimChannels_SetFlag mode, bool onlysel, bool flush)
 {
        ListBase anim_data = {NULL, NULL};
        ListBase all_data = {NULL, NULL};
@@ -1739,7 +1820,7 @@ static void setflag_anim_channels(bAnimContext *ac, short setting, short mode, s
                        ANIM_flush_setting_anim_channels(ac, &all_data, ale, setting, mode);
        }
        
-       BLI_freelistN(&anim_data);
+       ANIM_animdata_freelist(&anim_data);
        BLI_freelistN(&all_data);
 }
 
@@ -1748,8 +1829,9 @@ static void setflag_anim_channels(bAnimContext *ac, short setting, short mode, s
 static int animchannels_setflag_exec(bContext *C, wmOperator *op)
 {
        bAnimContext ac;
-       short mode, setting;
-       short flush = 1;
+       eAnimChannel_Settings setting;
+       eAnimChannels_SetFlag mode;
+       bool flush = true;
        
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -1761,12 +1843,12 @@ static int animchannels_setflag_exec(bContext *C, wmOperator *op)
        
        /* check if setting is flushable */
        if (setting == ACHANNEL_SETTING_EXPAND)
-               flush = 0;
+               flush = false;
        
        /* modify setting 
         *      - only selected channels are affected
         */
-       setflag_anim_channels(&ac, setting, mode, 1, flush);
+       setflag_anim_channels(&ac, setting, mode, true, flush);
        
        /* send notifier that things have changed */
        WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
@@ -1879,7 +1961,7 @@ static void ANIM_OT_channels_editable_toggle(wmOperatorType *ot)
 static int animchannels_expand_exec(bContext *C, wmOperator *op)
 {
        bAnimContext ac;
-       short onlysel = 1;
+       bool onlysel = true;
        
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -1887,10 +1969,10 @@ static int animchannels_expand_exec(bContext *C, wmOperator *op)
                
        /* only affect selected channels? */
        if (RNA_boolean_get(op->ptr, "all"))
-               onlysel = 0;
+               onlysel = false;
        
        /* modify setting */
-       setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_ADD, onlysel, 0);
+       setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_ADD, onlysel, false);
        
        /* send notifier that things have changed */
        WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
@@ -1921,7 +2003,7 @@ static void ANIM_OT_channels_expand(wmOperatorType *ot)
 static int animchannels_collapse_exec(bContext *C, wmOperator *op)
 {
        bAnimContext ac;
-       short onlysel = 1;
+       bool onlysel = true;
        
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -1929,10 +2011,10 @@ static int animchannels_collapse_exec(bContext *C, wmOperator *op)
                
        /* only affect selected channels? */
        if (RNA_boolean_get(op->ptr, "all"))
-               onlysel = 0;
+               onlysel = false;
        
        /* modify setting */
-       setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_CLEAR, onlysel, 0);
+       setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_CLEAR, onlysel, false);
        
        /* send notifier that things have changed */
        WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
@@ -1955,7 +2037,114 @@ static void ANIM_OT_channels_collapse(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
        
        /* props */
-       ot->prop = RNA_def_boolean(ot->srna, "all", 1, "All", "Collapse all channels (not just selected ones)");
+       ot->prop = RNA_def_boolean(ot->srna, "all", true, "All", "Collapse all channels (not just selected ones)");
+}
+
+/* ************ Remove All "Empty" AnimData Blocks Operator ********* */
+/* We define "empty" AnimData blocks here as those which have all 3 of criteria:
+ *  1) No active action OR that active actions are empty
+ *     Assuming that all legitimate entries will have an action,
+ *     and that empty actions
+ *  2) No NLA Tracks + NLA Strips
+ *     Assuming that users haven't set up any of these as "placeholders"
+ *     for convenience sake, and that most that exist were either unintentional
+ *     or are no longer wanted
+ *  3) No drivers
+ */
+static int animchannels_clean_empty_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       bAnimContext ac;
+       
+       ListBase anim_data = {NULL, NULL};
+       bAnimListElem *ale;
+       int filter;
+       
+       /* get editor data */
+       if (ANIM_animdata_get_context(C, &ac) == 0)
+               return OPERATOR_CANCELLED;
+       
+       /* get animdata blocks */
+       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA);
+       ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+       
+       for (ale = anim_data.first; ale; ale = ale->next) {
+               ID *id = ale->id;
+               AnimData *adt = ale->data;
+               
+               bool action_empty  = false;
+               bool nla_empty     = false;
+               bool drivers_empty = false;
+               
+               /* sanity checks */
+               BLI_assert((id != NULL) && (adt != NULL));
+               
+               /* check if this is "empty" and can be deleted */
+               /* (For now, there are only these 3 criteria) */
+               
+               /* 1) Active Action is missing or empty */
+               if (ELEM(NULL, adt->action, adt->action->curves.first)) {
+                       action_empty = true;
+               }
+               else {
+                       /* TODO: check for keyframe + fmodifier data on these too */
+               }
+               
+               /* 2) No NLA Tracks and/or NLA Strips */
+               if (adt->nla_tracks.first == NULL) {
+                       nla_empty = true;
+               }
+               else {
+                       NlaTrack *nlt;
+                       
+                       /* empty tracks? */
+                       for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
+                               if (nlt->strips.first) {
+                                       /* stop searching, as we found one that actually had stuff we don't want lost 
+                                        * NOTE: nla_empty gets reset to false, as a previous track may have been empty
+                                        */
+                                       nla_empty = false;
+                                       break;
+                               }
+                               else if (nlt->strips.first == NULL) {
+                                       /* this track is empty, but another one may still have stuff in it, so can't break yet */
+                                       nla_empty = true;
+                               }
+                       }
+               }
+               
+               /* 3) Drivers */
+               drivers_empty = (adt->drivers.first == NULL);
+               
+               
+               /* remove AnimData? */
+               if (action_empty && nla_empty && drivers_empty) {
+                       BKE_animdata_free(id, true);
+               }
+       }
+       
+       /* free temp data */
+       ANIM_animdata_freelist(&anim_data);
+       
+       /* send notifier that things have changed */
+       WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+       
+       return OPERATOR_FINISHED;
+}
+
+static void ANIM_OT_channels_clean_empty(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Remove Empty Animation Data";
+       ot->idname = "ANIM_OT_channels_clean_empty";
+       ot->description = "Delete all empty animation data containers from visible datablocks";
+       
+       /* api callbacks */
+       ot->exec = animchannels_clean_empty_exec;
+       ot->poll = animedit_poll_channels_nla_tweakmode_off;
+       
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /* ******************* Reenable Disabled Operator ******************* */
@@ -1963,7 +2152,7 @@ static void ANIM_OT_channels_collapse(wmOperatorType *ot)
 static int animchannels_enable_poll(bContext *C)
 {
        ScrArea *sa = CTX_wm_area(C);
-
+       
        /* channels region test */
        /* TODO: could enhance with actually testing if channels region? */
        if (ELEM(NULL, sa, CTX_wm_region(C)))
@@ -2004,11 +2193,11 @@ static int animchannels_enable_exec(bContext *C, wmOperator *UNUSED(op))
                        fcu->driver->flag &= ~DRIVER_FLAG_INVALID;
                        
                /* tag everything for updates - in particular, this is needed to get drivers working again */
-               ANIM_list_elem_update(ac.scene, ale);
+               ale->update |= ANIM_UPDATE_DEPS;
        }
        
-       /* free temp data */
-       BLI_freelistN(&anim_data);
+       ANIM_animdata_update(&ac, &anim_data);
+       ANIM_animdata_freelist(&anim_data);
                
        /* send notifier that things have changed */
        WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
@@ -2031,6 +2220,82 @@ static void ANIM_OT_channels_fcurves_enable(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
+/* ****************** Find / Set Filter Operator ******************** */
+
+/* XXX: make this generic? */
+static int animchannels_find_poll(bContext *C)
+{
+       ScrArea *sa = CTX_wm_area(C);
+       
+       if (sa == NULL)
+               return 0;
+       
+       /* animation editor with dopesheet */
+       return ELEM(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA);
+}
+
+/* find_invoke() - Get initial channels */
+static int animchannels_find_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
+{
+       bAnimContext ac;
+       
+       /* get editor data */
+       if (ANIM_animdata_get_context(C, &ac) == 0)
+               return OPERATOR_CANCELLED;
+       
+       /* set initial filter text, and enable filter */
+       RNA_string_set(op->ptr, "query", ac.ads->searchstr);
+       
+       /* defer to popup */
+       return WM_operator_props_popup(C, op, evt);
+}
+
+/* find_exec() -  Called to set the value */
+static int animchannels_find_exec(bContext *C, wmOperator *op)
+{
+       bAnimContext ac;
+       
+       /* get editor data */
+       if (ANIM_animdata_get_context(C, &ac) == 0)
+               return OPERATOR_CANCELLED;
+       
+       /* update filter text, and ensure that filter is enabled if there's something there
+        * NOTE: we turn the filter off if there's nothing (this is a quick shortcut for dismissing)
+        */
+       RNA_string_get(op->ptr, "query", ac.ads->searchstr);
+       
+       if (ac.ads->searchstr[0]) {
+               ac.ads->filterflag |= ADS_FILTER_BY_FCU_NAME;
+       }
+       else {
+               ac.ads->filterflag &= ~ADS_FILTER_BY_FCU_NAME;
+       }
+       
+       /* redraw */
+       WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+       
+       return OPERATOR_FINISHED;
+}
+
+static void ANIM_OT_channels_find(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Find Channels";
+       ot->idname = "ANIM_OT_channels_find";
+       ot->description = "Filter the set of channels shown to only include those with matching names";
+       
+       /* callbacks */
+       ot->invoke = animchannels_find_invoke;
+       ot->exec = animchannels_find_exec;
+       ot->poll = animchannels_find_poll;
+       
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+       
+       /* properties */
+       ot->prop = RNA_def_string(ot->srna, "query", "Query", sizeof(((bDopeSheet *)NULL)->searchstr), "", "Text to search for in channel names");
+}
+
 /* ********************** Select All Operator *********************** */
 
 static int animchannels_deselectall_exec(bContext *C, wmOperator *op)
@@ -2043,9 +2308,9 @@ static int animchannels_deselectall_exec(bContext *C, wmOperator *op)
                
        /* 'standard' behavior - check if selected, then apply relevant selection */
        if (RNA_boolean_get(op->ptr, "invert"))
-               ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, 0, ACHANNEL_SETFLAG_TOGGLE);
+               ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, false, ACHANNEL_SETFLAG_INVERT);
        else
-               ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, 1, ACHANNEL_SETFLAG_ADD);
+               ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, true, ACHANNEL_SETFLAG_ADD);
        
        /* send notifier that things have changed */
        WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
@@ -2068,7 +2333,7 @@ static void ANIM_OT_channels_select_all_toggle(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
        
        /* props */
-       ot->prop = RNA_def_boolean(ot->srna, "invert", 0, "Invert", "");
+       ot->prop = RNA_def_boolean(ot->srna, "invert", false, "Invert", "");
 }
 
 /* ******************** Borderselect Operator *********************** */
@@ -2091,7 +2356,7 @@ static void borderselect_anim_channels(bAnimContext *ac, rcti *rect, short selec
        }
        else {
                ymin = 0.0f;
-               ymax = (float)(-ACHANNEL_HEIGHT);
+               ymax = (float)(-ACHANNEL_HEIGHT(ac));
        }
        
        /* convert border-region to view coordinates */
@@ -2107,7 +2372,7 @@ static void borderselect_anim_channels(bAnimContext *ac, rcti *rect, short selec
                if (ac->datatype == ANIMCONT_NLA)
                        ymin = ymax - NLACHANNEL_STEP(snla);
                else
-                       ymin = ymax - ACHANNEL_STEP;
+                       ymin = ymax - ACHANNEL_STEP(ac);
                
                /* if channel is within border-select region, alter it */
                if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
@@ -2120,6 +2385,32 @@ static void borderselect_anim_channels(bAnimContext *ac, rcti *rect, short selec
                                {
                                        bActionGroup *agrp = (bActionGroup *)ale->data;
                                        
+                                       /* Armatures-Specific Feature:
+                                        * See mouse_anim_channels() -> ANIMTYPE_GROUP case for more details (T38737)
+                                        */
+                                       if ((ac->ads->filterflag & ADS_FILTER_ONLYSEL) == 0) {
+                                               if ((ale->id) && (GS(ale->id->name) == ID_OB)) {
+                                                       Object *ob = (Object *)ale->id;
+                                                       
+                                                       if (ob->type == OB_ARMATURE) {
+                                                               /* Assume for now that any group with corresponding name is what we want
+                                                                * (i.e. for an armature whose location is animated, things would break
+                                                                * if the user were to add a bone named "Location").
+                                                                *
+                                                                * TODO: check the first F-Curve or so to be sure...
+                                                                */
+                                                               bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, agrp->name);
+                                                               
+                                                               if (agrp->flag & AGRP_SELECTED) {
+                                                                       ED_pose_bone_select(ob, pchan, true);
+                                                               }
+                                                               else {
+                                                                       ED_pose_bone_select(ob, pchan, false);
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       
                                        /* always clear active flag after doing this */
                                        agrp->flag &= ~AGRP_ACTIVE;
                                        break;
@@ -2142,7 +2433,7 @@ static void borderselect_anim_channels(bAnimContext *ac, rcti *rect, short selec
        }
        
        /* cleanup */
-       BLI_freelistN(&anim_data);
+       ANIM_animdata_freelist(&anim_data);
 }
 
 /* ------------------- */
@@ -2152,7 +2443,8 @@ static int animchannels_borderselect_exec(bContext *C, wmOperator *op)
        bAnimContext ac;
        rcti rect;
        short selectmode = 0;
-       int gesture_mode, extend;
+       int gesture_mode;
+       bool extend;
        
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -2165,7 +2457,7 @@ static int animchannels_borderselect_exec(bContext *C, wmOperator *op)
        extend = RNA_boolean_get(op->ptr, "extend");
 
        if (!extend)
-               ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, 1, ACHANNEL_SETFLAG_CLEAR);
+               ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, true, ACHANNEL_SETFLAG_CLEAR);
 
        if (gesture_mode == GESTURE_MODAL_SELECT)
                selectmode = ACHANNEL_SETFLAG_ADD;
@@ -2200,18 +2492,19 @@ static void ANIM_OT_channels_select_border(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
        
        /* rna */
-       WM_operator_properties_gesture_border(ot, TRUE);
+       WM_operator_properties_gesture_border(ot, true);
 }
 
 /* ******************* Rename Operator ***************************** */
 /* Allow renaming some channels by clicking on them */
 
-static void rename_anim_channels(bAnimContext *ac, int channel_index)
+static bool rename_anim_channels(bAnimContext *ac, int channel_index)
 {
        ListBase anim_data = {NULL, NULL};
-       bAnimChannelType *acf;
+       const bAnimChannelType *acf;
        bAnimListElem *ale;
        int filter;
+       bool success = false;
        
        /* get the channel that was clicked on */
        /* filter channels */
@@ -2225,8 +2518,8 @@ static void rename_anim_channels(bAnimContext *ac, int channel_index)
                if (G.debug & G_DEBUG)
                        printf("Error: animation channel (index = %d) not found in rename_anim_channels()\n", channel_index);
                
-               BLI_freelistN(&anim_data);
-               return;
+               ANIM_animdata_freelist(&anim_data);
+               return false;
        }
        
        /* check that channel can be renamed */
@@ -2246,29 +2539,26 @@ static void rename_anim_channels(bAnimContext *ac, int channel_index)
                         */
                        if (ac->ads) {
                                ac->ads->renameIndex = channel_index + 1;
+                               success = true;
                        }
                }
        }
        
        /* free temp data and tag for refresh */
-       BLI_freelistN(&anim_data);
+       ANIM_animdata_freelist(&anim_data);
        ED_region_tag_redraw(ac->ar);
+       return success;
 }
 
-static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+static int animchannels_channel_get(bAnimContext *ac, const int mval[2])
 {
-       bAnimContext ac;
        ARegion *ar;
        View2D *v2d;
        int channel_index;
        float x, y;
        
-       /* get editor data */
-       if (ANIM_animdata_get_context(C, &ac) == 0)
-               return OPERATOR_CANCELLED;
-               
        /* get useful pointers from animation context data */
-       ar = ac.ar;
+       ar = ac->ar;
        v2d = &ar->v2d;
        
        /* figure out which channel user clicked in 
@@ -2276,20 +2566,36 @@ static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const
         *              so that the tops of channels get caught ok. Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use
         *              ACHANNEL_HEIGHT_HALF.
         */
-       UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y);
+       UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
        
-       if (ac.datatype == ANIMCONT_NLA) {
-               SpaceNla *snla = (SpaceNla *)ac.sl;
+       if (ac->datatype == ANIMCONT_NLA) {
+               SpaceNla *snla = (SpaceNla *)ac->sl;
                UI_view2d_listview_view_to_cell(v2d, NLACHANNEL_NAMEWIDTH, NLACHANNEL_STEP(snla), 0, (float)NLACHANNEL_HEIGHT_HALF(snla), x, y, NULL, &channel_index);
        }
        else {
-               UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP, 0, (float)ACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index);
+               UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP(ac), 0, (float)ACHANNEL_HEIGHT_HALF(ac), x, y, NULL, &channel_index);
        }
-       
+
+       return channel_index;
+}
+
+static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+       bAnimContext ac;
+       int channel_index;
+
+       /* get editor data */
+       if (ANIM_animdata_get_context(C, &ac) == 0)
+               return OPERATOR_CANCELLED;
+
+       channel_index = animchannels_channel_get(&ac, event->mval);
+
        /* handle click */
-       rename_anim_channels(&ac, channel_index);
-       
-       return OPERATOR_FINISHED;
+       if (rename_anim_channels(&ac, channel_index))
+               return OPERATOR_FINISHED;
+       else
+               /* allow event to be handled by selectall operator */
+               return OPERATOR_PASS_THROUGH;
 }
 
 static void ANIM_OT_channels_rename(wmOperatorType *ot)
@@ -2307,7 +2613,7 @@ static void ANIM_OT_channels_rename(wmOperatorType *ot)
 /* ******************** Mouse-Click Operator *********************** */
 /* Handle selection changes due to clicking on channels. Settings will get caught by UI code... */
 
-static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_index, short selectmode)
+static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index, short selectmode)
 {
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
@@ -2326,7 +2632,7 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
                if (G.debug & G_DEBUG)
                        printf("Error: animation channel (index = %d) not found in mouse_anim_channels()\n", channel_index);
                
-               BLI_freelistN(&anim_data);
+               ANIM_animdata_freelist(&anim_data);
                return 0;
        }
 
@@ -2334,7 +2640,7 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
        /* TODO: should this feature be extended to work with other channel types too? */
        if ((selectmode == -1) && (ale->type != ANIMTYPE_GROUP)) {
                /* normal channels should not behave normally in this case */
-               BLI_freelistN(&anim_data);
+               ANIM_animdata_freelist(&anim_data);
                return 0;
        }
 
@@ -2393,9 +2699,16 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
                                if (adt) adt->flag |= ADT_UI_SELECTED;
                        }
                        
+                       /* change active object - regardless of whether it is now selected [T37883] */
+                       ED_base_object_activate(C, base); /* adds notifier */
+                       
                        if ((adt) && (adt->flag & ADT_UI_SELECTED))
                                adt->flag |= ADT_UI_ACTIVE;
                        
+                       /* ensure we exit editmode on whatever object was active before to avoid getting stuck there - T48747 */
+                       if (ob != sce->obedit)
+                               ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
+                       
                        notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
                        break;
                }
@@ -2403,10 +2716,10 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
                case ANIMTYPE_DSMAT:    /* Datablock AnimData Expanders */
                case ANIMTYPE_DSLAM:
                case ANIMTYPE_DSCAM:
+               case ANIMTYPE_DSCACHEFILE:
                case ANIMTYPE_DSCUR:
                case ANIMTYPE_DSSKEY:
                case ANIMTYPE_DSWOR:
-               case ANIMTYPE_DSPART:
                case ANIMTYPE_DSMBALL:
                case ANIMTYPE_DSARM:
                case ANIMTYPE_DSMESH:
@@ -2415,6 +2728,7 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
                case ANIMTYPE_DSLAT:
                case ANIMTYPE_DSLINESTYLE:
                case ANIMTYPE_DSSPK:
+               case ANIMTYPE_DSGPENCIL:
                {
                        /* sanity checking... */
                        if (ale->adt) {
@@ -2425,7 +2739,7 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
                                }
                                else {
                                        /* select AnimData block by itself */
-                                       ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+                                       ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
                                        ale->adt->flag |= ADT_UI_SELECTED;
                                }
                                
@@ -2441,6 +2755,35 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
                {
                        bActionGroup *agrp = (bActionGroup *)ale->data;
                        
+                       Object *ob = NULL;
+                       bPoseChannel *pchan = NULL;
+                       
+                       
+                       /* Armatures-Specific Feature:
+                        * Since groups are used to collect F-Curves of the same Bone by default
+                        * (via Keying Sets) so that they can be managed better, we try to make
+                        * things here easier for animators by mapping group selection to bone
+                        * selection. 
+                        *
+                        * Only do this if "Only Selected" dopesheet filter is not active, or else it
+                        * becomes too unpredictable/tricky to manage
+                        */
+                       if ((ac->ads->filterflag & ADS_FILTER_ONLYSEL) == 0) {
+                               if ((ale->id) && (GS(ale->id->name) == ID_OB)) {
+                                       ob = (Object *)ale->id;
+                                       
+                                       if (ob->type == OB_ARMATURE) {
+                                               /* Assume for now that any group with corresponding name is what we want
+                                                * (i.e. for an armature whose location is animated, things would break
+                                                * if the user were to add a bone named "Location").
+                                                *
+                                                * TODO: check the first F-Curve or so to be sure...
+                                                */
+                                               pchan = BKE_pose_channel_find_name(ob->pose, agrp->name);
+                                       }       
+                               }
+                       }
+                       
                        /* select/deselect group */
                        if (selectmode == SELECT_INVERT) {
                                /* inverse selection status of this group only */
@@ -2451,7 +2794,8 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
                                FCurve *fcu;
                                
                                /* deselect all other channels */
-                               ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+                               ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
+                               if (pchan) ED_pose_de_selectall(ob, SEL_DESELECT, false);
                                
                                /* only select channels in group and group itself */
                                for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcu->next)
@@ -2460,20 +2804,27 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
                        }
                        else {
                                /* select group by itself */
-                               ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+                               ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
+                               if (pchan) ED_pose_de_selectall(ob, SEL_DESELECT, false);
+                               
                                agrp->flag |= AGRP_SELECTED;
                        }
                        
                        /* if group is selected now, make group the 'active' one in the visible list */
-                       if (agrp->flag & AGRP_SELECTED)
+                       if (agrp->flag & AGRP_SELECTED) {
                                ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
-                       else
+                               if (pchan) ED_pose_bone_select(ob, pchan, true);
+                       }
+                       else {
                                ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, NULL, ANIMTYPE_GROUP);
+                               if (pchan) ED_pose_bone_select(ob, pchan, false);
+                       }
                                
                        notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
                        break;
                }
-               case ANIMTYPE_FCURVE: 
+               case ANIMTYPE_FCURVE:
+               case ANIMTYPE_NLACURVE:
                {
                        FCurve *fcu = (FCurve *)ale->data;
                        
@@ -2484,13 +2835,13 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
                        }
                        else {
                                /* select F-Curve by itself */
-                               ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+                               ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
                                fcu->flag |= FCURVE_SELECTED;
                        }
                        
                        /* if F-Curve is selected now, make F-Curve the 'active' one in the visible list */
                        if (fcu->flag & FCURVE_SELECTED)
-                               ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
+                               ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type);
                                
                        notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
                        break;
@@ -2506,13 +2857,26 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
                        }
                        else {
                                /* select ShapeKey by itself */
-                               ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+                               ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
                                kb->flag |= KEYBLOCK_SEL;
                        }
                                
                        notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
                        break;
                }
+               case ANIMTYPE_NLACONTROLS:
+               {
+                       AnimData *adt = (AnimData *)ale->data;
+                       
+                       /* toggle expand
+                        *   - Although the triangle widget already allows this, since there's nothing else that can be done here now,
+                        *     let's just use it for easier expand/collapse for now
+                        */
+                       adt->flag ^= ADT_NLA_SKEYS_COLLAPSED;
+                       
+                       notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
+                       break;
+               }
                case ANIMTYPE_GPDATABLOCK:
                {
                        bGPdata *gpd = (bGPdata *)ale->data;
@@ -2536,11 +2900,17 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
                        }
                        else {
                                /* select layer by itself */
-                               ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+                               ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
                                gpl->flag |= GP_LAYER_SELECT;
                        }
                        
-                       notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
+                       /* change active layer, if this is selected (since we must always have an active layer) */
+                       if (gpl->flag & GP_LAYER_SELECT) {
+                               ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, gpl, ANIMTYPE_GPLAYER);
+                       }
+                       
+                       WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); /* Grease Pencil updates */
+                       notifierFlags |= (ND_ANIMCHAN | NA_EDITED); /* Animation Ediotrs updates */
                        break;
                }
                case ANIMTYPE_MASKDATABLOCK:
@@ -2566,7 +2936,7 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
                        }
                        else {
                                /* select layer by itself */
-                               ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+                               ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
                                masklay->flag |= MASK_LAYERFLAG_SELECT;
                        }
                        
@@ -2576,10 +2946,11 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
                default:
                        if (G.debug & G_DEBUG)
                                printf("Error: Invalid channel type in mouse_anim_channels()\n");
+                       break;
        }
        
        /* free channels */
-       BLI_freelistN(&anim_data);
+       ANIM_animdata_freelist(&anim_data);
        
        /* return notifier flags */
        return notifierFlags;
@@ -2621,10 +2992,10 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmE
         *              ACHANNEL_HEIGHT_HALF.
         */
        UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y);
-       UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP, 0, (float)ACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index);
+       UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP(&ac), 0, (float)ACHANNEL_HEIGHT_HALF(&ac), x, y, NULL, &channel_index);
        
        /* handle mouse-click in the relevant channel then */
-       notifierFlags = mouse_anim_channels(&ac, x, channel_index, selectmode);
+       notifierFlags = mouse_anim_channels(C, &ac, channel_index, selectmode);
        
        /* set notifier that things have changed */
        WM_event_add_notifier(C, NC_ANIMATION | notifierFlags, NULL);
@@ -2650,10 +3021,109 @@ static void ANIM_OT_channels_click(wmOperatorType *ot)
        
        /* properties */
        /* NOTE: don't save settings, otherwise, can end up with some weird behaviour (sticky extend) */
-       prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
+       prop = RNA_def_boolean(ot->srna, "extend", false, "Extend Select", ""); // SHIFTKEY
        RNA_def_property_flag(prop, PROP_SKIP_SAVE);
        
-       prop = RNA_def_boolean(ot->srna, "children_only", 0, "Select Children Only", ""); // CTRLKEY|SHIFTKEY
+       prop = RNA_def_boolean(ot->srna, "children_only", false, "Select Children Only", ""); // CTRLKEY|SHIFTKEY
+       RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
+static bool select_anim_channel_keys(bAnimContext *ac, int channel_index, bool extend)
+{
+       ListBase anim_data = {NULL, NULL};
+       bAnimListElem *ale;
+       int filter;
+       bool success = false;
+       FCurve *fcu;
+       int i;
+
+       /* get the channel that was clicked on */
+       /* filter channels */
+       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+       /* get channel from index */
+       ale = BLI_findlink(&anim_data, channel_index);
+       if (ale == NULL) {
+               /* channel not found */
+               if (G.debug & G_DEBUG)
+                       printf("Error: animation channel (index = %d) not found in rename_anim_channels()\n", channel_index);
+
+               ANIM_animdata_freelist(&anim_data);
+               return false;
+       }
+
+       fcu = (FCurve *)ale->key_data;
+       success = (fcu != NULL);
+
+       ANIM_animdata_freelist(&anim_data);
+
+       /* F-Curve may not have any keyframes */
+       if (fcu && fcu->bezt) {
+               BezTriple *bezt;
+
+               if (!extend) {
+                       filter = (ANIMFILTER_DATA_VISIBLE);
+                       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+                       for (ale = anim_data.first; ale; ale = ale->next) {
+                               FCurve *fcu_inner = (FCurve *)ale->key_data;
+
+                               if (fcu_inner) {
+                                       for (i = 0, bezt = fcu_inner->bezt; i < fcu_inner->totvert; i++, bezt++) {
+                                               bezt->f2 = bezt->f1 = bezt->f3 = 0;
+                                       }
+                               }
+                       }
+
+                       ANIM_animdata_freelist(&anim_data);
+               }
+
+               for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+                       bezt->f2 = bezt->f1 = bezt->f3 = SELECT;
+               }
+       }
+
+       /* free temp data and tag for refresh */
+       ED_region_tag_redraw(ac->ar);
+       return success;
+}
+
+static int animchannels_channel_select_keys_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+       bAnimContext ac;
+       int channel_index;
+       bool extend = RNA_boolean_get(op->ptr, "extend");
+
+       /* get editor data */
+       if (ANIM_animdata_get_context(C, &ac) == 0)
+               return OPERATOR_CANCELLED;
+
+       channel_index = animchannels_channel_get(&ac, event->mval);
+
+       /* handle click */
+       if (select_anim_channel_keys(&ac, channel_index, extend)) {
+               WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+               return OPERATOR_FINISHED;
+       }
+       else
+               /* allow event to be handled by selectall operator */
+               return OPERATOR_PASS_THROUGH;
+}
+
+static void ANIM_OT_channel_select_keys(wmOperatorType *ot)
+{
+       PropertyRNA *prop;
+
+       /* identifiers */
+       ot->name = "Select Channel keyframes";
+       ot->idname = "ANIM_OT_channel_select_keys";
+       ot->description = "Select all keyframes of channel under mouse";
+
+       /* api callbacks */
+       ot->invoke = animchannels_channel_select_keys_invoke;
+       ot->poll = animedit_poll_channels_active;
+
+       prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection");
        RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 }
 
@@ -2666,7 +3136,10 @@ void ED_operatortypes_animchannels(void)
        WM_operatortype_append(ANIM_OT_channels_select_border);
        
        WM_operatortype_append(ANIM_OT_channels_click);
+       WM_operatortype_append(ANIM_OT_channel_select_keys);
        WM_operatortype_append(ANIM_OT_channels_rename);
+
+       WM_operatortype_append(ANIM_OT_channels_find);
        
        WM_operatortype_append(ANIM_OT_channels_setting_enable);
        WM_operatortype_append(ANIM_OT_channels_setting_disable);
@@ -2682,11 +3155,10 @@ void ED_operatortypes_animchannels(void)
        WM_operatortype_append(ANIM_OT_channels_expand);
        WM_operatortype_append(ANIM_OT_channels_collapse);
        
-       WM_operatortype_append(ANIM_OT_channels_visibility_toggle);
-       WM_operatortype_append(ANIM_OT_channels_visibility_set);
-       
        WM_operatortype_append(ANIM_OT_channels_fcurves_enable);
        
+       WM_operatortype_append(ANIM_OT_channels_clean_empty);
+       
        WM_operatortype_append(ANIM_OT_channels_group);
        WM_operatortype_append(ANIM_OT_channels_ungroup);
 }
@@ -2696,20 +3168,25 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
 {
        wmKeyMap *keymap = WM_keymap_find(keyconf, "Animation Channels", 0, 0);
        wmKeyMapItem *kmi;
-
-       /* selection */
+       
        /* click-select */
        /* XXX for now, only leftmouse.... */
        WM_keymap_add_item(keymap, "ANIM_OT_channels_click", LEFTMOUSE, KM_PRESS, 0, 0);
-       RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_click", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", TRUE);
-       RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_click", LEFTMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "children_only", TRUE);
+       RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_click", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", true);
+       RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_click", LEFTMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "children_only", true);
 
        /* rename */
        WM_keymap_add_item(keymap, "ANIM_OT_channels_rename", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
+       WM_keymap_add_item(keymap, "ANIM_OT_channels_rename", LEFTMOUSE, KM_DBL_CLICK, 0, 0);
+       WM_keymap_add_item(keymap, "ANIM_OT_channel_select_keys", LEFTMOUSE, KM_DBL_CLICK, 0, 0);
+       RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channel_select_keys", LEFTMOUSE, KM_DBL_CLICK, KM_SHIFT, 0)->ptr, "extend", true);
+
+       /* find (i.e. a shortcut for setting the name filter) */
+       WM_keymap_add_item(keymap, "ANIM_OT_channels_find", FKEY, KM_PRESS, KM_CTRL, 0);
        
        /* deselect all */
        WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", AKEY, KM_PRESS, 0, 0);
-       RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", TRUE);
+       RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", true);
        
        /* borderselect */
        WM_keymap_add_item(keymap, "ANIM_OT_channels_select_border", BKEY, KM_PRESS, 0, 0);
@@ -2732,9 +3209,9 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
        WM_keymap_add_item(keymap, "ANIM_OT_channels_collapse", PADMINUS, KM_PRESS, 0, 0);
        
        kmi = WM_keymap_add_item(keymap, "ANIM_OT_channels_expand", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
-       RNA_boolean_set(kmi->ptr, "all", FALSE);
+       RNA_boolean_set(kmi->ptr, "all", false);
        kmi = WM_keymap_add_item(keymap, "ANIM_OT_channels_collapse", PADMINUS, KM_PRESS, KM_CTRL, 0);
-       RNA_boolean_set(kmi->ptr, "all", FALSE);
+       RNA_boolean_set(kmi->ptr, "all", false);
 
        /* rearranging */
        RNA_enum_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_move", PAGEUPKEY, KM_PRESS, 0, 0)->ptr, "direction", REARRANGE_ANIMCHAN_UP);
@@ -2745,10 +3222,6 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
        /* grouping */
        WM_keymap_add_item(keymap, "ANIM_OT_channels_group", GKEY, KM_PRESS, KM_CTRL, 0);
        WM_keymap_add_item(keymap, "ANIM_OT_channels_ungroup", GKEY, KM_PRESS, KM_ALT, 0);
-       
-       /* Graph Editor only */
-       WM_keymap_add_item(keymap, "ANIM_OT_channels_visibility_set", VKEY, KM_PRESS, 0, 0);
-       WM_keymap_add_item(keymap, "ANIM_OT_channels_visibility_toggle", VKEY, KM_PRESS, KM_SHIFT, 0);
 }
 
 /* ************************************************************************** */