Merged changes in the trunk up to revision 54802.
[blender.git] / source / blender / editors / animation / anim_channels_edit.c
index ec1583f2aa3cbb099ff8cf032fc90b466c25c09c..15a8222dec28bfd731d422521c77b0290b5a971a 100644 (file)
@@ -43,6 +43,7 @@
 #include "DNA_scene_types.h"
 #include "DNA_key_types.h"
 #include "DNA_gpencil_types.h"
+#include "DNA_mask_types.h"
 
 #include "RNA_access.h"
 #include "RNA_define.h"
@@ -51,6 +52,7 @@
 #include "BKE_fcurve.h"
 #include "BKE_gpencil.h"
 #include "BKE_context.h"
+#include "BKE_mask.h"
 #include "BKE_global.h"
 
 #include "UI_view2d.h"
@@ -69,7 +71,7 @@
 
 /* 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, short datatype, int filter, void *channel_data, short channel_type)
 {
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
@@ -80,7 +82,7 @@ void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int
                return;
                
        /* only clear the 'active' flag for the channels of the same type */
-       for (ale= anim_data.first; ale; ale= ale->next) {
+       for (ale = anim_data.first; ale; ale = ale->next) {
                /* skip if types don't match */
                if (channel_type != ale->type)
                        continue;
@@ -89,28 +91,28 @@ void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int
                switch (ale->type) {
                        case ANIMTYPE_GROUP:
                        {
-                               bActionGroup *agrp= (bActionGroup *)ale->data;
+                               bActionGroup *agrp = (bActionGroup *)ale->data;
                                
                                ACHANNEL_SET_FLAG(agrp, ACHANNEL_SETFLAG_CLEAR, AGRP_ACTIVE);
                        }
-                               break;
+                       break;
                        case ANIMTYPE_FCURVE:
                        {
-                               FCurve *fcu= (FCurve *)ale->data;
+                               FCurve *fcu = (FCurve *)ale->data;
                                
                                ACHANNEL_SET_FLAG(fcu, ACHANNEL_SETFLAG_CLEAR, FCURVE_ACTIVE);
                        }
-                               break;
+                       break;
                        case ANIMTYPE_NLATRACK:
                        {
-                               NlaTrack *nlt= (NlaTrack *)ale->data;
+                               NlaTrack *nlt = (NlaTrack *)ale->data;
                                
                                ACHANNEL_SET_FLAG(nlt, ACHANNEL_SETFLAG_CLEAR, NLATRACK_ACTIVE);
                        }
-                               break;
+                       break;
                        
                        case ANIMTYPE_FILLACTD: /* Action Expander */
-                       case ANIMTYPE_DSMAT:    /* Datablock AnimData Expanders */
+                       case ANIMTYPE_DSMAT:    /* Datablock AnimData Expanders */
                        case ANIMTYPE_DSLAM:
                        case ANIMTYPE_DSCAM:
                        case ANIMTYPE_DSCUR:
@@ -122,6 +124,9 @@ void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int
                        case ANIMTYPE_DSMESH:
                        case ANIMTYPE_DSTEX:
                        case ANIMTYPE_DSLAT:
+#ifdef WITH_FREESTYLE
+                       case ANIMTYPE_DSLINESTYLE:
+#endif
                        case ANIMTYPE_DSSPK:
                        {
                                /* need to verify that this data is valid for now */
@@ -129,7 +134,7 @@ void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int
                                        ACHANNEL_SET_FLAG(ale->adt, ACHANNEL_SETFLAG_CLEAR, ADT_UI_ACTIVE);
                                }
                        }
-                               break;
+                       break;
                }
        }
        
@@ -138,25 +143,25 @@ void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int
                switch (channel_type) {
                        case ANIMTYPE_GROUP:
                        {
-                               bActionGroup *agrp= (bActionGroup *)channel_data;
+                               bActionGroup *agrp = (bActionGroup *)channel_data;
                                agrp->flag |= AGRP_ACTIVE;
                        }
-                               break;
+                       break;
                        case ANIMTYPE_FCURVE:
                        {
-                               FCurve *fcu= (FCurve *)channel_data;
+                               FCurve *fcu = (FCurve *)channel_data;
                                fcu->flag |= FCURVE_ACTIVE;
                        }
-                               break;
+                       break;
                        case ANIMTYPE_NLATRACK:
                        {
-                               NlaTrack *nlt= (NlaTrack *)channel_data;
+                               NlaTrack *nlt = (NlaTrack *)channel_data;
                                nlt->flag |= NLATRACK_ACTIVE;
                        }
-                               break;
+                       break;
                                
                        case ANIMTYPE_FILLACTD: /* Action Expander */
-                       case ANIMTYPE_DSMAT:    /* Datablock AnimData Expanders */
+                       case ANIMTYPE_DSMAT:    /* Datablock AnimData Expanders */
                        case ANIMTYPE_DSLAM:
                        case ANIMTYPE_DSCAM:
                        case ANIMTYPE_DSCUR:
@@ -167,6 +172,9 @@ void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int
                        case ANIMTYPE_DSARM:
                        case ANIMTYPE_DSMESH:
                        case ANIMTYPE_DSLAT:
+#ifdef WITH_FREESTYLE
+                       case ANIMTYPE_DSLINESTYLE:
+#endif
                        case ANIMTYPE_DSSPK:
                        {
                                /* need to verify that this data is valid for now */
@@ -174,7 +182,7 @@ void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int
                                        ale->adt->flag |= ADT_UI_ACTIVE;
                                }
                        }
-                               break;
+                       break;
                }
        }
        
@@ -188,7 +196,7 @@ void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int
  *     - 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, short datatype, short test, short sel)
 {
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
@@ -196,45 +204,45 @@ void ANIM_deselect_anim_channels (bAnimContext *ac, void *data, short datatype,
        
        /* filter data */
        /* NOTE: no list visible, otherwise, we get dangling */
-       filter= ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS;
+       filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS;
        ANIM_animdata_filter(ac, &anim_data, filter, data, datatype);
        
        /* See if we should be selecting or deselecting */
        if (test) {
-               for (ale= anim_data.first; ale; ale= ale->next) {
+               for (ale = anim_data.first; ale; ale = ale->next) {
                        if (sel == 0) 
                                break;
                        
                        switch (ale->type) {
                                case ANIMTYPE_SCENE:
                                        if (ale->flag & SCE_DS_SELECTED)
-                                               sel= ACHANNEL_SETFLAG_CLEAR;
+                                               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;
+                                               sel = ACHANNEL_SETFLAG_CLEAR;
                                #endif
                                        break;
                                case ANIMTYPE_GROUP:
                                        if (ale->flag & AGRP_SELECTED)
-                                               sel= ACHANNEL_SETFLAG_CLEAR;
+                                               sel = ACHANNEL_SETFLAG_CLEAR;
                                        break;
                                case ANIMTYPE_FCURVE:
                                        if (ale->flag & FCURVE_SELECTED)
-                                               sel= ACHANNEL_SETFLAG_CLEAR;
+                                               sel = ACHANNEL_SETFLAG_CLEAR;
                                        break;
                                case ANIMTYPE_SHAPEKEY:
                                        if (ale->flag & KEYBLOCK_SEL)
-                                               sel= ACHANNEL_SETFLAG_CLEAR;
+                                               sel = ACHANNEL_SETFLAG_CLEAR;
                                        break;
                                case ANIMTYPE_NLATRACK:
                                        if (ale->flag & NLATRACK_SELECTED)
-                                               sel= ACHANNEL_SETFLAG_CLEAR;
+                                               sel = ACHANNEL_SETFLAG_CLEAR;
                                        break;
                                        
                                case ANIMTYPE_FILLACTD: /* Action Expander */
-                               case ANIMTYPE_DSMAT:    /* Datablock AnimData Expanders */
+                               case ANIMTYPE_DSMAT:    /* Datablock AnimData Expanders */
                                case ANIMTYPE_DSLAM:
                                case ANIMTYPE_DSCAM:
                                case ANIMTYPE_DSCUR:
@@ -247,27 +255,34 @@ void ANIM_deselect_anim_channels (bAnimContext *ac, void *data, short datatype,
                                case ANIMTYPE_DSNTREE:
                                case ANIMTYPE_DSTEX:
                                case ANIMTYPE_DSLAT:
+#ifdef WITH_FREESTYLE
+                               case ANIMTYPE_DSLINESTYLE:
+#endif
                                case ANIMTYPE_DSSPK:
                                {
                                        if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED))
-                                               sel= ACHANNEL_SETFLAG_CLEAR;
+                                               sel = ACHANNEL_SETFLAG_CLEAR;
                                }
-                                       break;
+                               break;
                                        
                                case ANIMTYPE_GPLAYER:
                                        if (ale->flag & GP_LAYER_SELECT)
-                                               sel= ACHANNEL_SETFLAG_CLEAR;
+                                               sel = ACHANNEL_SETFLAG_CLEAR;
+                                       break;
+                               case ANIMTYPE_MASKLAYER:
+                                       if (ale->flag & MASK_LAYERFLAG_SELECT)
+                                               sel = ACHANNEL_SETFLAG_CLEAR;
                                        break;
                        }
                }
        }
                
        /* Now set the flags */
-       for (ale= anim_data.first; ale; ale= ale->next) {
+       for (ale = anim_data.first; ale; ale = ale->next) {
                switch (ale->type) {
                        case ANIMTYPE_SCENE:
                        {
-                               Scene *scene= (Scene *)ale->data;
+                               Scene *scene = (Scene *)ale->data;
                                
                                ACHANNEL_SET_FLAG(scene, sel, SCE_DS_SELECTED);
                                
@@ -275,56 +290,56 @@ void ANIM_deselect_anim_channels (bAnimContext *ac, void *data, short datatype,
                                        ACHANNEL_SET_FLAG(scene, sel, ADT_UI_SELECTED);
                                }
                        }
-                               break;
+                       break;
                        case ANIMTYPE_OBJECT:
-                       #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;
-                               
-                               ACHANNEL_SET_FLAG(base, sel, SELECT);
-                               ACHANNEL_SET_FLAG(ob, sel, SELECT);
-                               
-                               if (ob->adt) {
-                                       ACHANNEL_SET_FLAG(ob, sel, ADT_UI_SELECTED);
+                       #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;
+                                       
+                                       ACHANNEL_SET_FLAG(base, sel, SELECT);
+                                       ACHANNEL_SET_FLAG(ob, sel, SELECT);
+                                       
+                                       if (ob->adt) {
+                                               ACHANNEL_SET_FLAG(ob, sel, ADT_UI_SELECTED);
+                                       }
                                }
-                       }
                        #endif
                                break;
                        case ANIMTYPE_GROUP:
                        {
-                               bActionGroup *agrp= (bActionGroup *)ale->data;
+                               bActionGroup *agrp = (bActionGroup *)ale->data;
                                
                                ACHANNEL_SET_FLAG(agrp, sel, AGRP_SELECTED);
                                agrp->flag &= ~AGRP_ACTIVE;
                        }
-                               break;
+                       break;
                        case ANIMTYPE_FCURVE:
                        {
-                               FCurve *fcu= (FCurve *)ale->data;
+                               FCurve *fcu = (FCurve *)ale->data;
                                
                                ACHANNEL_SET_FLAG(fcu, sel, FCURVE_SELECTED);
                                fcu->flag &= ~FCURVE_ACTIVE;
                        }
-                               break;
+                       break;
                        case ANIMTYPE_SHAPEKEY:
                        {
-                               KeyBlock *kb= (KeyBlock *)ale->data;
+                               KeyBlock *kb = (KeyBlock *)ale->data;
                                
                                ACHANNEL_SET_FLAG(kb, sel, KEYBLOCK_SEL);
                        }
-                               break;
+                       break;
                        case ANIMTYPE_NLATRACK:
                        {
-                               NlaTrack *nlt= (NlaTrack *)ale->data;
+                               NlaTrack *nlt = (NlaTrack *)ale->data;
                                
                                ACHANNEL_SET_FLAG(nlt, sel, NLATRACK_SELECTED);
                                nlt->flag &= ~NLATRACK_ACTIVE;
                        }
-                               break;
+                       break;
                                
                        case ANIMTYPE_FILLACTD: /* Action Expander */
-                       case ANIMTYPE_DSMAT:    /* Datablock AnimData Expanders */
+                       case ANIMTYPE_DSMAT:    /* Datablock AnimData Expanders */
                        case ANIMTYPE_DSLAM:
                        case ANIMTYPE_DSCAM:
                        case ANIMTYPE_DSCUR:
@@ -337,6 +352,9 @@ void ANIM_deselect_anim_channels (bAnimContext *ac, void *data, short datatype,
                        case ANIMTYPE_DSNTREE:
                        case ANIMTYPE_DSTEX:
                        case ANIMTYPE_DSLAT:
+#ifdef WITH_FREESTYLE
+                       case ANIMTYPE_DSLINESTYLE:
+#endif
                        case ANIMTYPE_DSSPK:
                        {
                                /* need to verify that this data is valid for now */
@@ -345,7 +363,7 @@ void ANIM_deselect_anim_channels (bAnimContext *ac, void *data, short datatype,
                                        ale->adt->flag &= ~ADT_UI_ACTIVE;
                                }
                        }
-                               break;
+                       break;
                                
                        case ANIMTYPE_GPLAYER:
                        {
@@ -353,7 +371,15 @@ void ANIM_deselect_anim_channels (bAnimContext *ac, void *data, short datatype,
                                
                                ACHANNEL_SET_FLAG(gpl, sel, GP_LAYER_SELECT);
                        }
-                               break;
+                       break;
+                       
+                       case ANIMTYPE_MASKLAYER:
+                       {
+                               MaskLayer *masklay = (MaskLayer *)ale->data;
+                               
+                               ACHANNEL_SET_FLAG(masklay, sel, MASK_LAYERFLAG_SELECT);
+                       }
+                       break;
                }
        }
        
@@ -372,44 +398,44 @@ void ANIM_deselect_anim_channels (bAnimContext *ac, void *data, short datatype,
  *     - 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, int setting, short on)
 {
-       bAnimListElem *ale, *match=NULL;
-       int prevLevel=0, matchLevel=0;
+       bAnimListElem *ale, *match = NULL;
+       int prevLevel = 0, matchLevel = 0;
        
        /* sanity check */
        if (ELEM(NULL, anim_data, anim_data->first))
                return;
        
        /* find the channel that got changed */
-       for (ale= anim_data->first; ale; ale= ale->next) {
+       for (ale = anim_data->first; ale; ale = ale->next) {
                /* compare data, and type as main way of identifying the channel */
                if ((ale->data == ale_setting->data) && (ale->type == ale_setting->type)) {
                        /* we also have to check the ID, this is assigned to, since a block may have multiple users */
-                       // TODO: is the owner-data more revealing?
+                       /* TODO: is the owner-data more revealing? */
                        if (ale->id == ale_setting->id) {
-                               match= ale;
+                               match = ale;
                                break;
                        }
                }
        }
        if (match == NULL) {
-               printf("ERROR: no channel matching the one changed was found \n");
+               printf("ERROR: no channel matching the one changed was found\n");
                return;
        }
        else {
-               bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale_setting);
+               bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale_setting);
                
                if (acf == NULL) {
-                       printf("ERROR: no channel info for the changed channel \n");
+                       printf("ERROR: no channel info for the changed channel\n");
                        return;
                }
                
                /* get the level of the channel that was affected
-                *       - we define the level as simply being the offset for the start of the channel
+                *   - we define the level as simply being the offset for the start of the channel
                 */
-               matchLevel= (acf->get_offset)? acf->get_offset(ac, ale_setting) : 0;
-               prevLevel= matchLevel;
+               matchLevel = (acf->get_offset) ? acf->get_offset(ac, ale_setting) : 0;
+               prevLevel = matchLevel;
        }
        
        /* flush up? 
@@ -423,11 +449,11 @@ void ANIM_flush_setting_anim_channels (bAnimContext *ac, ListBase *anim_data, bA
         *        (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) )
+            ((setting != ACHANNEL_SETTING_VISIBLE) && on == 0) )
        {
                /* 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);
+               for (ale = match->prev; ale; ale = ale->prev) {
+                       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 */
@@ -435,9 +461,9 @@ void ANIM_flush_setting_anim_channels (bAnimContext *ac, ListBase *anim_data, bA
                                continue;
                        
                        /* get the level of the current channel traversed 
-                        *       - we define the level as simply being the offset for the start of the channel
+                        *   - we define the level as simply being the offset for the start of the channel
                         */
-                       level= (acf->get_offset)? acf->get_offset(ac, ale) : 0;
+                       level = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
                        
                        /* if the level is 'less than' (i.e. more important) the level we're matching
                         * but also 'less than' the level just tried (i.e. only the 1st group above grouped F-Curves, 
@@ -449,8 +475,8 @@ void ANIM_flush_setting_anim_channels (bAnimContext *ac, ListBase *anim_data, bA
                                ANIM_channel_setting_set(ac, ale, setting, on);
                                
                                /* store this level as the 'old' level now */
-                               prevLevel= level;
-                       }       
+                               prevLevel = level;
+                       }
                        /* if the level is 'greater than' (i.e. less important) than the previous level... */
                        else if (level > prevLevel) {
                                /* if previous level was a base-level (i.e. 0 offset / root of one hierarchy),
@@ -470,8 +496,8 @@ void ANIM_flush_setting_anim_channels (bAnimContext *ac, ListBase *anim_data, bA
        /* flush down (always) */
        {
                /* 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);
+               for (ale = match->next; ale; ale = ale->next) {
+                       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 */
@@ -479,9 +505,9 @@ void ANIM_flush_setting_anim_channels (bAnimContext *ac, ListBase *anim_data, bA
                                continue;
                        
                        /* get the level of the current channel traversed 
-                        *       - we define the level as simply being the offset for the start of the channel
+                        *   - we define the level as simply being the offset for the start of the channel
                         */
-                       level= (acf->get_offset)? acf->get_offset(ac, ale) : 0;
+                       level = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
                        
                        /* if the level is 'greater than' (i.e. less important) the channel that was changed, 
                         * flush the new status...
@@ -496,7 +522,7 @@ void ANIM_flush_setting_anim_channels (bAnimContext *ac, ListBase *anim_data, bA
                                break;
                        
                        /* store this level as the 'old' level now */
-                       // prevLevel= level; // XXX: prevLevel is unused
+                       // prevLevel = level; // XXX: prevLevel is unused
                }
        }
 }
@@ -504,7 +530,7 @@ void ANIM_flush_setting_anim_channels (bAnimContext *ac, ListBase *anim_data, bA
 /* -------------------------- F-Curves ------------------------------------- */
 
 /* Delete the given F-Curve from its AnimData block */
-void ANIM_fcurve_delete_from_animdata (bAnimContext *ac, AnimData *adt, FCurve *fcu)
+void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, AnimData *adt, FCurve *fcu)
 {
        /* - if no AnimData, we've got nowhere to remove the F-Curve from 
         *      (this doesn't guarantee that the F-Curve is in there, but at least we tried
@@ -524,12 +550,26 @@ void ANIM_fcurve_delete_from_animdata (bAnimContext *ac, AnimData *adt, FCurve *
                BLI_remlink(&adt->drivers, fcu);
        }
        else if (adt->action) {
+               bAction *act = adt->action;
+               
                /* remove from group or action, whichever one "owns" the F-Curve */
-               if (fcu->grp)
-                       action_groups_remove_channel(adt->action, fcu);
-               else
-                       BLI_remlink(&adt->action->curves, fcu);
+               if (fcu->grp) {
+                       bActionGroup *agrp = fcu->grp;
+                       
+                       /* remove F-Curve from group+action */
+                       action_groups_remove_channel(act, fcu);
                        
+                       /* if group has no more channels, remove it too, 
+                        * otherwise can have many dangling groups [#33541]
+                        */
+                       if (agrp->channels.first == NULL) {
+                               BLI_freelinkN(&act->groups, agrp);
+                       }
+               }
+               else {
+                       BLI_remlink(&act->curves, fcu);
+               }
+               
                /* if action has no more F-Curves as a result of this, unlink it from
                 * AnimData if it did not come from a NLA Strip being tweaked.
                 *
@@ -537,12 +577,8 @@ void ANIM_fcurve_delete_from_animdata (bAnimContext *ac, AnimData *adt, FCurve *
                 * channel list that are empty, and linger around long after the data they
                 * are for has disappeared (and probably won't come back).
                 */
-                       // XXX: does everybody always want this?
-                       /* XXX: there's a problem where many actions could build up in the file if multiple
-                        * full add/delete cycles are performed on the same objects, but assume that this is rare
-                        */
-               if ((adt->action->curves.first == NULL) && (adt->flag & ADT_NLA_EDIT_ON)==0) {
-                       id_us_min(&adt->action->id);
+               if ((act->curves.first == NULL) && (adt->flag & ADT_NLA_EDIT_ON) == 0) {
+                       id_us_min(&act->id);
                        adt->action = NULL;
                }
        }
@@ -557,36 +593,36 @@ void ANIM_fcurve_delete_from_animdata (bAnimContext *ac, AnimData *adt, FCurve *
 /* ****************** Operator Utilities ********************************** */
 
 /* poll callback for being in an Animation Editor channels list region */
-static int animedit_poll_channels_active (bContext *C)
+static int animedit_poll_channels_active(bContext *C)
 {
-       ScrArea *sa= CTX_wm_area(C);
+       ScrArea *sa = CTX_wm_area(C);
        
        /* channels region test */
-       // TODO: could enhance with actually testing if channels region?
+       /* TODO: could enhance with actually testing if channels region? */
        if (ELEM(NULL, sa, CTX_wm_region(C)))
                return 0;
        /* animation editor test */
        if (ELEM3(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0)
                return 0;
-               
+
        return 1;
 }
 
 /* poll callback for Animation Editor channels list region + not in NLA-tweakmode for NLA */
-static int animedit_poll_channels_nla_tweakmode_off (bContext *C)
+static int animedit_poll_channels_nla_tweakmode_off(bContext *C)
 {
-       ScrArea *sa= CTX_wm_area(C);
+       ScrArea *sa = CTX_wm_area(C);
        Scene *scene = CTX_data_scene(C);
-       
+
        /* channels region test */
-       // TODO: could enhance with actually testing if channels region?
+       /* TODO: could enhance with actually testing if channels region? */
        if (ELEM(NULL, sa, CTX_wm_region(C)))
                return 0;
        /* animation editor test */
        if (ELEM3(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0)
                return 0;
        
-       /* NLA TweakMode test */        
+       /* NLA TweakMode test */
        if (sa->spacetype == SPACE_NLA) {
                if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON))
                        return 0;
@@ -600,10 +636,10 @@ static int animedit_poll_channels_nla_tweakmode_off (bContext *C)
 /* constants for channel rearranging */
 /* WARNING: don't change exising ones without modifying rearrange func accordingly */
 enum {
-       REARRANGE_ANIMCHAN_TOP= -2,
-       REARRANGE_ANIMCHAN_UP= -1,
-       REARRANGE_ANIMCHAN_DOWN= 1,
-       REARRANGE_ANIMCHAN_BOTTOM= 2
+       REARRANGE_ANIMCHAN_TOP = -2,
+       REARRANGE_ANIMCHAN_UP = -1,
+       REARRANGE_ANIMCHAN_DOWN = 1,
+       REARRANGE_ANIMCHAN_BOTTOM = 2
 };
 
 /* defines for rearranging channels */
@@ -621,21 +657,21 @@ static EnumPropertyItem prop_animchannel_rearrange_types[] = {
 typedef struct tReorderChannelIsland {
        struct tReorderChannelIsland *next, *prev;
        
-       ListBase channels;      /* channels within this region with the same state */
-       int flag;                       /* eReorderIslandFlag */
+       ListBase channels;  /* channels within this region with the same state */
+       int flag;           /* eReorderIslandFlag */
 } tReorderChannelIsland;
 
 /* flags for channel reordering islands */
 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_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 */
 } eReorderIslandFlag;
 
 
 /* Rearrange Methods --------------------------------------------- */
 
-static short rearrange_island_ok (tReorderChannelIsland *island)
+static short rearrange_island_ok(tReorderChannelIsland *island)
 {
        /* island must not be untouchable */
        if (island->flag & REORDER_ISLAND_UNTOUCHABLE)
@@ -647,7 +683,7 @@ static short rearrange_island_ok (tReorderChannelIsland *island)
 
 /* ............................. */
 
-static short rearrange_island_top (ListBase *list, tReorderChannelIsland *island)
+static short rearrange_island_top(ListBase *list, tReorderChannelIsland *island)
 {
        if (rearrange_island_ok(island)) {
                /* remove from current position */
@@ -662,11 +698,11 @@ static short rearrange_island_top (ListBase *list, tReorderChannelIsland *island
        return 0;
 }
 
-static short rearrange_island_up (ListBase *list, tReorderChannelIsland *island)
+static short 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;
+               tReorderChannelIsland *prev = island->prev;
                
                if (prev) {
                        /* remove from current position */
@@ -682,7 +718,7 @@ static short rearrange_island_up (ListBase *list, tReorderChannelIsland *island)
        return 0;
 }
 
-static short rearrange_island_down (ListBase *list, tReorderChannelIsland *island)
+static short 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 */
@@ -690,7 +726,7 @@ static short rearrange_island_down (ListBase *list, tReorderChannelIsland *islan
                
                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) {
+                       if ((next->flag & REORDER_ISLAND_UNTOUCHABLE) == 0) {
                                /* remove from current position */
                                BLI_remlink(list, island);
                                
@@ -706,7 +742,7 @@ static short rearrange_island_down (ListBase *list, tReorderChannelIsland *islan
        return 0;
 }
 
-static short rearrange_island_bottom (ListBase *list, tReorderChannelIsland *island)
+static short rearrange_island_bottom(ListBase *list, tReorderChannelIsland *island)
 {
        if (rearrange_island_ok(island)) {
                tReorderChannelIsland *last = list->last;
@@ -715,7 +751,7 @@ static short rearrange_island_bottom (ListBase *list, tReorderChannelIsland *isl
                BLI_remlink(list, island);
                
                /* add before or after the last channel? */
-               if ((last->flag & REORDER_ISLAND_UNTOUCHABLE)==0) {
+               if ((last->flag & REORDER_ISLAND_UNTOUCHABLE) == 0) {
                        /* can add after it */
                        BLI_addtail(list, island);
                }
@@ -741,7 +777,7 @@ static short rearrange_island_bottom (ListBase *list, tReorderChannelIsland *isl
 typedef short (*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(short mode)
 {
        switch (mode) {
                case REARRANGE_ANIMCHAN_TOP:
@@ -760,35 +796,35 @@ 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, short type)
 {
-       tReorderChannelIsland *island = islands->last;  /* always try to add to last island if possible */
-       short is_sel=0, is_untouchable=0;
+       tReorderChannelIsland *island = islands->last;  /* always try to add to last island if possible */
+       short is_sel = 0, is_untouchable = 0;
        
        /* get flags - selected and untouchable from the channel */
        switch (type) {
                case ANIMTYPE_GROUP:
                {
-                       bActionGroup *agrp= (bActionGroup *)channel;
+                       bActionGroup *agrp = (bActionGroup *)channel;
                        
-                       is_sel= SEL_AGRP(agrp);
-                       is_untouchable= (agrp->flag & AGRP_TEMP) != 0;
+                       is_sel = SEL_AGRP(agrp);
+                       is_untouchable = (agrp->flag & AGRP_TEMP) != 0;
                }
-                       break;
+               break;
                case ANIMTYPE_FCURVE:
                {
-                       FCurve *fcu= (FCurve *)channel;
+                       FCurve *fcu = (FCurve *)channel;
                        
-                       is_sel= SEL_FCU(fcu);
-               }       
-                       break;
+                       is_sel = SEL_FCU(fcu);
+               }
+               break;
                case ANIMTYPE_NLATRACK:
                {
-                       NlaTrack *nlt= (NlaTrack *)channel;
+                       NlaTrack *nlt = (NlaTrack *)channel;
                        
-                       is_sel= SEL_NLT(nlt);
+                       is_sel = SEL_NLT(nlt);
                }
-                       break;
+               break;
                        
                default:
                        printf("rearrange_animchannel_add_to_islands(): don't know how to handle channels of type %d\n", type);
@@ -797,8 +833,8 @@ static void rearrange_animchannel_add_to_islands (ListBase *islands, ListBase *s
        
        /* 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) */
+           ((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) */
        {
                /* create a new island now */
                island = MEM_callocN(sizeof(tReorderChannelIsland), "tReorderChannelIsland");
@@ -816,9 +852,9 @@ static void rearrange_animchannel_add_to_islands (ListBase *islands, ListBase *s
 }
 
 /* flatten islands out into a single list again */
-static void rearrange_animchannel_flatten_islands (ListBase *islands, ListBase *srcList)
+static void rearrange_animchannel_flatten_islands(ListBase *islands, ListBase *srcList)
 {
-       tReorderChannelIsland *island, *isn=NULL;
+       tReorderChannelIsland *island, *isn = NULL;
        
        /* make sure srcList is empty now */
        BLI_assert(srcList->first == NULL);
@@ -836,11 +872,11 @@ static void rearrange_animchannel_flatten_islands (ListBase *islands, ListBase *
 /* ............................. */
 
 /* performing rearranging of channels using islands */
-static short rearrange_animchannel_islands (ListBase *list, AnimChanRearrangeFp rearrange_func, short mode, short type)
+static short rearrange_animchannel_islands(ListBase *list, AnimChanRearrangeFp rearrange_func, short mode, short type)
 {
        ListBase islands = {NULL, NULL};
-       Link *channel, *chanNext=NULL;
-       short done = 0;
+       Link *channel, *chanNext = NULL;
+       short done = FALSE;
        
        /* don't waste effort on an empty list */
        if (list->first == NULL)
@@ -858,7 +894,7 @@ static short rearrange_animchannel_islands (ListBase *list, AnimChanRearrangeFp
         */
        if (islands.first != islands.last) {
                tReorderChannelIsland *first = (mode > 0) ? islands.last : islands.first;
-               tReorderChannelIsland *island, *isn=NULL;
+               tReorderChannelIsland *island, *isn = NULL;
                
                for (island = first; island; island = isn) {
                        isn = (mode > 0) ? island->prev : island->next;
@@ -866,7 +902,7 @@ static short rearrange_animchannel_islands (ListBase *list, AnimChanRearrangeFp
                        /* perform rearranging */
                        if (rearrange_func(&islands, island)) {
                                island->flag |= REORDER_ISLAND_MOVED;
-                               done = 1;
+                               done = TRUE;
                        }
                }
        }
@@ -884,7 +920,7 @@ static short rearrange_animchannel_islands (ListBase *list, AnimChanRearrangeFp
  * ! 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 *UNUSED(ac), AnimData *adt, short mode)
 {
        AnimChanRearrangeFp rearrange_func;
        
@@ -896,7 +932,7 @@ static void rearrange_nla_channels (bAnimContext *UNUSED(ac), AnimData *adt, sho
        if (rearrange_func == NULL)
                return;
        
-       /* only consider NLA data if it's accessible */ 
+       /* only consider NLA data if it's accessible */
        //if (EXPANDED_DRVD(adt) == 0)
        //      return;
        
@@ -909,7 +945,7 @@ static void rearrange_nla_channels (bAnimContext *UNUSED(ac), AnimData *adt, sho
 /* 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 *UNUSED(ac), AnimData *adt, short mode)
 {
        /* get rearranging function */
        AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
@@ -917,7 +953,7 @@ static void rearrange_driver_channels (bAnimContext *UNUSED(ac), AnimData *adt,
        if (rearrange_func == NULL)
                return;
        
-       /* only consider drivers if they're accessible */       
+       /* only consider drivers if they're accessible */
        if (EXPANDED_DRVD(adt) == 0)
                return;
        
@@ -928,7 +964,7 @@ static void rearrange_driver_channels (bAnimContext *UNUSED(ac), AnimData *adt,
 /* Action Specific Stuff ------------------------------------------------- */
 
 /* make sure all action-channels belong to a group (and clear action's list) */
-static void split_groups_action_temp (bAction *act, bActionGroup *tgrp)
+static void split_groups_action_temp(bAction *act, bActionGroup *tgrp)
 {
        bActionGroup *agrp;
        FCurve *fcu;
@@ -937,37 +973,37 @@ static void split_groups_action_temp (bAction *act, bActionGroup *tgrp)
                return;
        
        /* Separate F-Curves into lists per group */
-       for (agrp= act->groups.first; agrp; agrp= agrp->next) {
+       for (agrp = act->groups.first; agrp; agrp = agrp->next) {
                if (agrp->channels.first) {
-                       fcu= agrp->channels.last;
-                       act->curves.first= fcu->next;
+                       fcu = agrp->channels.last;
+                       act->curves.first = fcu->next;
                        
-                       fcu= agrp->channels.first;
-                       fcu->prev= NULL;
+                       fcu = agrp->channels.first;
+                       fcu->prev = NULL;
                        
-                       fcu= agrp->channels.last;
-                       fcu->next= NULL;
+                       fcu = agrp->channels.last;
+                       fcu->next = NULL;
                }
        }
        
        /* Initialize memory for temp-group */
        memset(tgrp, 0, sizeof(bActionGroup));
-       tgrp->flag |= (AGRP_EXPANDED|AGRP_TEMP);
+       tgrp->flag |= (AGRP_EXPANDED | AGRP_TEMP);
        BLI_strncpy(tgrp->name, "#TempGroup", sizeof(tgrp->name));
        
        /* Move any action-channels not already moved, to the temp group */
        if (act->curves.first) {
                /* start of list */
-               fcu= act->curves.first;
-               fcu->prev= NULL;
-               tgrp->channels.first= fcu;
-               act->curves.first= NULL;
+               fcu = act->curves.first;
+               fcu->prev = NULL;
+               tgrp->channels.first = fcu;
+               act->curves.first = NULL;
                
                /* end of list */
-               fcu= act->curves.last;
-               fcu->next= NULL;
-               tgrp->channels.last= fcu;
-               act->curves.last= NULL;
+               fcu = act->curves.last;
+               fcu->next = NULL;
+               tgrp->channels.last = fcu;
+               act->curves.last = NULL;
        }
        
        /* Add temp-group to list */
@@ -975,17 +1011,17 @@ static void split_groups_action_temp (bAction *act, bActionGroup *tgrp)
 }
 
 /* link lists of channels that groups have */
-static void join_groups_action_temp (bAction *act)
+static void join_groups_action_temp(bAction *act)
 {
        bActionGroup *agrp;
        
-       for (agrp= act->groups.first; agrp; agrp= agrp->next) {
+       for (agrp = act->groups.first; agrp; agrp = agrp->next) {
                ListBase tempGroup;
                
                /* add list of channels to action's channels */
-               tempGroup= agrp->channels;
+               tempGroup = agrp->channels;
                BLI_movelisttolist(&act->curves, &agrp->channels);
-               agrp->channels= tempGroup;
+               agrp->channels = tempGroup;
                
                /* clear moved flag */
                agrp->flag &= ~AGRP_MOVED;
@@ -1001,7 +1037,7 @@ 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, short mode)
 {
        bActionGroup tgrp;
        short do_channels;
@@ -1024,7 +1060,7 @@ static void rearrange_action_channels (bAnimContext *ac, bAction *act, short mod
        if (do_channels) {
                bActionGroup *agrp;
                
-               for (agrp= act->groups.first; agrp; agrp= agrp->next) {
+               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);
@@ -1048,13 +1084,17 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
                return OPERATOR_CANCELLED;
                
        /* get mode */
-       mode= RNA_enum_get(op->ptr, "direction");
+       mode = RNA_enum_get(op->ptr, "direction");
        
        /* 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");
        }
+       else if (ac.datatype == ANIMCONT_MASK) {
+               /* Grease Pencil channels */
+               printf("Mask does not supported for moving yet\n");
+       }
        else if (ac.datatype == ANIMCONT_ACTION) {
                /* Directly rearrange action's channels */
                rearrange_action_channels(&ac, ac.data, mode);
@@ -1065,11 +1105,11 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
                int filter;
                
                /* get animdata blocks */
-               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA);
+               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) {
-                       AnimData *adt= ale->data;
+                       AnimData *adt = ale->data;
                        
                        switch (ac.datatype) {
                                case ANIMCONT_NLA: /* NLA-tracks only */
@@ -1085,7 +1125,7 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
                                default: /* some collection of actions */
                                        if (adt->action)
                                                rearrange_action_channels(&ac, adt->action, mode);
-                                       else if (G.f & G_DEBUG)
+                                       else if (G.debug & G_DEBUG)
                                                printf("Animdata has no action\n");
                                        break;
                        }
@@ -1096,27 +1136,239 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
        }
        
        /* send notifier that things have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
        
        return OPERATOR_FINISHED;
 }
 
-static void ANIM_OT_channels_move (wmOperatorType *ot)
+static void ANIM_OT_channels_move(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Move Channels";
-       ot->idname= "ANIM_OT_channels_move";
+       ot->name = "Move Channels";
+       ot->idname = "ANIM_OT_channels_move";
        ot->description = "Rearrange selected animation channels";
        
        /* api callbacks */
-       ot->exec= animchannels_rearrange_exec;
-       ot->poll= animedit_poll_channels_nla_tweakmode_off;
+       ot->exec = animchannels_rearrange_exec;
+       ot->poll = animedit_poll_channels_nla_tweakmode_off;
+       
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+       
+       /* props */
+       ot->prop = RNA_def_enum(ot->srna, "direction", prop_animchannel_rearrange_types, REARRANGE_ANIMCHAN_DOWN, "Direction", "");
+}
+
+/* ******************** Group Channel Operator ************************ */
+
+static int animchannels_grouping_poll(bContext *C)
+{
+       ScrArea *sa = CTX_wm_area(C);
+       SpaceLink *sl;
+
+       /* channels region test */
+       /* TODO: could enhance with actually testing if channels region? */
+       if (ELEM(NULL, sa, CTX_wm_region(C)))
+               return 0;
+               
+       /* animation editor test - must be suitable modes only */
+       sl = CTX_wm_space_data(C);
+       
+       switch (sa->spacetype) {
+               /* supported... */
+               case SPACE_ACTION:
+               {
+                       SpaceAction *saction = (SpaceAction *)sl;
+                       
+                       /* 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;
+                       
+                       /* drivers can't have groups... */
+                       if (sipo->mode != SIPO_MODE_ANIMATION)
+                               return 0;
+               }
+                       break;
+                       
+               /* unsupported... */
+               default:
+                       return 0;
+       }
+       
+       return 1;
+}
+
+/* ----------------------------------------------------------- */
+
+static void animchannels_group_channels(bAnimContext *ac, bAnimListElem *adt_ref, const char name[])
+{      
+       AnimData *adt = adt_ref->adt;
+       bAction *act = adt->action;
+       
+       if (act) {
+               ListBase anim_data = {NULL, NULL};
+               int filter;
+               
+               /* find selected F-Curves to re-group */
+               filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL);
+               ANIM_animdata_filter(ac, &anim_data, filter, adt_ref, ANIMCONT_CHANNEL);
+               
+               if (anim_data.first) {
+                       bActionGroup *agrp;
+                       bAnimListElem *ale;
+                       
+                       /* create new group, which should now be part of the action */
+                       agrp = action_groups_add_new(act, name);
+                       BLI_assert(agrp != NULL);
+                       
+                       /* transfer selected F-Curves across to new group  */
+                       for (ale = anim_data.first; ale; ale = ale->next) {
+                               FCurve *fcu = (FCurve *)ale->data;
+                               bActionGroup *grp = fcu->grp;
+                               
+                               /* 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)) {
+                                       BLI_freelinkN(&act->groups, grp);
+                               }
+                               
+                               /* add F-Curve to group */
+                               action_groups_add_channel(act, agrp, fcu);
+                       }
+               }
+               
+               /* cleanup */
+               BLI_freelistN(&anim_data);
+       }
+}
+
+static int animchannels_group_exec(bContext *C, wmOperator *op)
+{
+       bAnimContext ac;
+       char name[MAX_NAME];
+       
+       /* get editor data */
+       if (ANIM_animdata_get_context(C, &ac) == 0)
+               return OPERATOR_CANCELLED;
+       
+       /* get name for new group */
+       RNA_string_get(op->ptr, "name", name);
+       
+       /* XXX: name for group should never be empty... */
+       if (name[0]) {
+               ListBase anim_data = {NULL, NULL};
+               bAnimListElem *ale;
+               int filter;
+               
+               /* handle each animdata block separately, so that the regrouping doesn't flow into blocks  */
+               filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA | ANIMFILTER_NODUPLIS);
+               ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+               
+               for (ale = anim_data.first; ale; ale = ale->next) {
+                       animchannels_group_channels(&ac, ale, name);
+               }
+               
+               /* free temp data */
+               BLI_freelistN(&anim_data);
+               
+               /* updatss */
+               WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+       }
+       
+       return OPERATOR_FINISHED;
+}
+
+static void ANIM_OT_channels_group(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Group Channels";
+       ot->idname = "ANIM_OT_channels_group";
+       ot->description = "Add selected F-Curves to a new group";
+       
+       /* callbacks */
+       ot->invoke = WM_operator_props_popup;
+       ot->exec = animchannels_group_exec;
+       ot->poll = animchannels_grouping_poll;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
        
        /* props */
-       ot->prop= RNA_def_enum(ot->srna, "direction", prop_animchannel_rearrange_types, REARRANGE_ANIMCHAN_DOWN, "Direction", "");
+       ot->prop = RNA_def_string(ot->srna, "name", "New Group", 
+                                 sizeof(((bActionGroup *)NULL)->name), 
+                                 "Name", "Name of newly created group");
+       /* RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); */ /* XXX: still not too sure about this - keeping same text is confusing... */
+}
+
+/* ----------------------------------------------------------- */
+
+static int animchannels_ungroup_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;
+               
+       /* just selected F-Curves... */
+       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
+       ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+       
+       for (ale = anim_data.first; ale; ale = ale->next) {
+               /* find action for this F-Curve... */
+               if (ale->adt && ale->adt->action) {
+                       FCurve  *fcu = (FCurve *)ale->data;
+                       bAction *act = ale->adt->action;
+                       
+                       /* only proceed to remove if F-Curve is in a group... */
+                       if (fcu->grp) { 
+                               bActionGroup *agrp = fcu->grp;
+                               
+                               /* remove F-Curve from group and add at tail (ungrouped) */
+                               action_groups_remove_channel(act, fcu);
+                               BLI_addtail(&act->curves, fcu);
+                               
+                               /* delete group if it is now empty */
+                               if (agrp->channels.first == NULL) {
+                                       BLI_freelinkN(&act->groups, agrp);
+                               }
+                       }
+               }
+       }
+       
+       /* cleanup */
+       BLI_freelistN(&anim_data);
+       
+       /* updates */
+       WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+       
+       return OPERATOR_FINISHED;
+}
+
+static void ANIM_OT_channels_ungroup(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Ungroup Channels";
+       ot->idname = "ANIM_OT_channels_ungroup";
+       ot->description = "Remove selected F-Curves from their current groups";
+       
+       /* callbacks */
+       ot->exec = animchannels_ungroup_exec;
+       ot->poll = animchannels_grouping_poll;
+       
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /* ******************** Delete Channel Operator *********************** */
@@ -1140,15 +1392,15 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
        /* do groups only first (unless in Drivers mode, where there are none) */
        if (ac.datatype != ANIMCONT_DRIVERS) {
                /* filter data */
-               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
+               filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
                ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
                
                /* delete selected groups and their associated channels */
-               for (ale= anim_data.first; ale; ale= ale->next) {
+               for (ale = anim_data.first; ale; ale = ale->next) {
                        /* only groups - don't check other types yet, since they may no-longer exist */
                        if (ale->type == ANIMTYPE_GROUP) {
-                               bActionGroup *agrp= (bActionGroup *)ale->data;
-                               AnimData *adt= ale->adt;
+                               bActionGroup *agrp = (bActionGroup *)ale->data;
+                               AnimData *adt = ale->adt;
                                FCurve *fcu, *fcn;
                                
                                /* skip this group if no AnimData available, as we can't safely remove the F-Curves */
@@ -1156,8 +1408,8 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
                                        continue;
                                
                                /* delete all of the Group's F-Curves, but no others */
-                               for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcn) {
-                                       fcn= fcu->next;
+                               for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcn) {
+                                       fcn = fcu->next;
                                        
                                        /* remove from group and action, then free */
                                        action_groups_remove_channel(adt->action, fcu);
@@ -1177,34 +1429,45 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
        }
        
        /* filter data */
-       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
+       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
        ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
        
        /* delete selected data channels */
-       for (ale= anim_data.first; ale; ale= ale->next) {
+       for (ale = anim_data.first; ale; ale = ale->next) {
                switch (ale->type) {
                        case ANIMTYPE_FCURVE: 
                        {
                                /* F-Curves if we can identify its parent */
-                               AnimData *adt= ale->adt;
-                               FCurve *fcu= (FCurve *)ale->data;
+                               AnimData *adt = ale->adt;
+                               FCurve *fcu = (FCurve *)ale->data;
                                
                                /* try to free F-Curve */
                                ANIM_fcurve_delete_from_animdata(&ac, adt, fcu);
                        }
-                               break;
+                       break;
                                
                        case ANIMTYPE_GPLAYER:
                        {
                                /* Grease Pencil layer */
-                               bGPdata *gpd= (bGPdata *)ale->id;
-                               bGPDlayer *gpl= (bGPDlayer *)ale->data;
+                               bGPdata *gpd = (bGPdata *)ale->id;
+                               bGPDlayer *gpl = (bGPDlayer *)ale->data;
                                
                                /* try to delete the layer's data and the layer itself */
                                free_gpencil_frames(gpl);
                                BLI_freelinkN(&gpd->layers, gpl);
                        }
-                               break;
+                       break;
+                       
+                       case ANIMTYPE_MASKLAYER:
+                       {
+                               /* Mask layer */
+                               Mask *mask = (Mask *)ale->id;
+                               MaskLayer *masklay = (MaskLayer *)ale->data;
+                               
+                               /* try to delete the layer's data and the layer itself */
+                               BKE_mask_layer_remove(mask, masklay);
+                       }
+                       break;
                }
        }
        
@@ -1212,24 +1475,24 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
        BLI_freelistN(&anim_data);
        
        /* send notifier that things have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
        
        return OPERATOR_FINISHED;
 }
  
-static void ANIM_OT_channels_delete (wmOperatorType *ot)
+static void ANIM_OT_channels_delete(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Delete Channels";
-       ot->idname= "ANIM_OT_channels_delete";
-       ot->description= "Delete all selected animation channels";
+       ot->name = "Delete Channels";
+       ot->idname = "ANIM_OT_channels_delete";
+       ot->description = "Delete all selected animation channels";
        
        /* api callbacks */
-       ot->exec= animchannels_delete_exec;
-       ot->poll= animedit_poll_channels_active;
+       ot->exec = animchannels_delete_exec;
+       ot->poll = animedit_poll_channels_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /* ******************** Set Channel Visibility Operator *********************** */
@@ -1250,7 +1513,7 @@ static int animchannels_visibility_set_exec(bContext *C, wmOperator *UNUSED(op))
        /* 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);
+       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
@@ -1262,15 +1525,15 @@ static int animchannels_visibility_set_exec(bContext *C, wmOperator *UNUSED(op))
         */
        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);
+               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);
+               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) {
+       for (ale = anim_data.first; ale; ale = ale->next) {
                /* clear setting first */
                ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR);
                
@@ -1283,12 +1546,12 @@ static int animchannels_visibility_set_exec(bContext *C, wmOperator *UNUSED(op))
        BLI_freelistN(&anim_data);
        
        /* make all the selected channels visible */
-       filter= (ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
+       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) {
+
+       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
+               /* TODO: find out why this is the case, and fix that */
                if (ale->type == ANIMTYPE_OBJECT)
                        continue;
                
@@ -1304,24 +1567,24 @@ static int animchannels_visibility_set_exec(bContext *C, wmOperator *UNUSED(op))
        
        
        /* send notifier that things have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
        
        return OPERATOR_FINISHED;
 }
 
-static void ANIM_OT_channels_visibility_set (wmOperatorType *ot)
+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";
+       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;
+       ot->exec = animchannels_visibility_set_exec;
+       ot->poll = ED_operator_graphedit_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 
@@ -1335,7 +1598,7 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *UNUSED(o
        ListBase all_data = {NULL, NULL};
        bAnimListElem *ale;
        int filter;
-       short vis= ACHANNEL_SETFLAG_ADD;
+       short vis = ACHANNEL_SETFLAG_ADD;
        
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -1344,28 +1607,28 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *UNUSED(o
        /* 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);
+       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);
+       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) {
+       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;
+                       vis = ACHANNEL_SETFLAG_CLEAR;
                        break;
                }
        }
 
        /* Now set the flags */
-       for (ale= anim_data.first; ale; ale= ale->next) {
+       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
+               /* TODO: find out why this is the case, and fix that */
                if (ale->type == ANIMTYPE_OBJECT)
                        continue;
                
@@ -1381,24 +1644,24 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *UNUSED(o
        BLI_freelistN(&all_data);
        
        /* send notifier that things have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
        
        return OPERATOR_FINISHED;
 }
 
-static void ANIM_OT_channels_visibility_toggle (wmOperatorType *ot)
+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";
+       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;
+       ot->exec = animchannels_visibility_toggle_exec;
+       ot->poll = ED_operator_graphedit_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /* ********************** Set Flags Operator *********************** */
@@ -1429,7 +1692,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, short setting, short mode, short onlysel, short flush)
 {
        ListBase anim_data = {NULL, NULL};
        ListBase all_data = {NULL, NULL};
@@ -1442,7 +1705,7 @@ static void setflag_anim_channels (bAnimContext *ac, short setting, short mode,
                 * - hierarchy visibility needs to be ignored so that settings can get flushed
                 *   "down" inside closed containers
                 */
-               filter= ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS;
+               filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS;
                ANIM_animdata_filter(ac, &all_data, filter, ac->data, ac->datatype);
        }
        
@@ -1455,11 +1718,11 @@ static void setflag_anim_channels (bAnimContext *ac, short setting, short mode,
         */
        if ((ac->spacetype == SPACE_IPO) && (ac->regiontype != RGN_TYPE_CHANNELS)) {
                /* graph editor (case 2) */
-               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
+               filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
        }
        else {
                /* standard case */
-               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
+               filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
        }
        if (onlysel) filter |= ANIMFILTER_SEL;
        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
@@ -1467,20 +1730,20 @@ static void setflag_anim_channels (bAnimContext *ac, short setting, short mode,
        /* if toggling, check if disable or enable */
        if (mode == ACHANNEL_SETFLAG_TOGGLE) {
                /* default to turn all on, unless we encounter one that's on... */
-               mode= ACHANNEL_SETFLAG_ADD;
+               mode = ACHANNEL_SETFLAG_ADD;
                
                /* see if we should turn off instead... */
-               for (ale= anim_data.first; ale; ale= ale->next) {
+               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, setting) > 0) {
-                               mode= ACHANNEL_SETFLAG_CLEAR;
+                               mode = ACHANNEL_SETFLAG_CLEAR;
                                break;
                        }
                }
        }
        
        /* apply the setting */
-       for (ale= anim_data.first; ale; ale= ale->next) {
+       for (ale = anim_data.first; ale; ale = ale->next) {
                /* skip channel if setting is not available */
                if (ANIM_channel_setting_get(ac, ale, setting) == -1)
                        continue;
@@ -1503,19 +1766,19 @@ static int animchannels_setflag_exec(bContext *C, wmOperator *op)
 {
        bAnimContext ac;
        short mode, setting;
-       short flush=1;
+       short flush = 1;
        
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
                return OPERATOR_CANCELLED;
                
        /* mode (eAnimChannels_SetFlag), setting (eAnimChannel_Settings) */
-       mode= RNA_enum_get(op->ptr, "mode");
-       setting= RNA_enum_get(op->ptr, "type");
+       mode = RNA_enum_get(op->ptr, "mode");
+       setting = RNA_enum_get(op->ptr, "type");
        
        /* check if setting is flushable */
        if (setting == ACHANNEL_SETTING_EXPAND)
-               flush= 0;
+               flush = 0;
        
        /* modify setting 
         *      - only selected channels are affected
@@ -1523,105 +1786,117 @@ static int animchannels_setflag_exec(bContext *C, wmOperator *op)
        setflag_anim_channels(&ac, setting, mode, 1, flush);
        
        /* send notifier that things have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
        
        return OPERATOR_FINISHED;
 }
 
 /* duplicate of 'ANIM_OT_channels_setting_toggle' for menu title only, weak! */
-static void ANIM_OT_channels_setting_enable (wmOperatorType *ot)
+static void ANIM_OT_channels_setting_enable(wmOperatorType *ot)
 {
+       PropertyRNA *prop;
+       
        /* identifiers */
-       ot->name= "Enable Channel Setting";
-       ot->idname= "ANIM_OT_channels_setting_enable";
-       ot->description= "Enable specified setting on all selected animation channels";
+       ot->name = "Enable Channel Setting";
+       ot->idname = "ANIM_OT_channels_setting_enable";
+       ot->description = "Enable specified setting on all selected animation channels";
        
        /* api callbacks */
-       ot->invoke= WM_menu_invoke;
-       ot->exec= animchannels_setflag_exec;
-       ot->poll= animedit_poll_channels_active;
+       ot->invoke = WM_menu_invoke;
+       ot->exec = animchannels_setflag_exec;
+       ot->poll = animedit_poll_channels_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
        
        /* props */
-               /* flag-setting mode */
-       RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_ADD, "Mode", "");
-               /* setting to set */
-       ot->prop= RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
+       /* flag-setting mode */
+       prop = RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_ADD, "Mode", "");
+       RNA_def_property_flag(prop, PROP_HIDDEN);
+       /* setting to set */
+       ot->prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
 }
 /* duplicate of 'ANIM_OT_channels_setting_toggle' for menu title only, weak! */
-static void ANIM_OT_channels_setting_disable (wmOperatorType *ot)
+static void ANIM_OT_channels_setting_disable(wmOperatorType *ot)
 {
+       PropertyRNA *prop;
+       
        /* identifiers */
-       ot->name= "Disable Channel Setting";
-       ot->idname= "ANIM_OT_channels_setting_disable";
-       ot->description= "Disable specified setting on all selected animation channels";
+       ot->name = "Disable Channel Setting";
+       ot->idname = "ANIM_OT_channels_setting_disable";
+       ot->description = "Disable specified setting on all selected animation channels";
        
        /* api callbacks */
-       ot->invoke= WM_menu_invoke;
-       ot->exec= animchannels_setflag_exec;
-       ot->poll= animedit_poll_channels_active;
+       ot->invoke = WM_menu_invoke;
+       ot->exec = animchannels_setflag_exec;
+       ot->poll = animedit_poll_channels_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
        
        /* props */
-               /* flag-setting mode */
-       RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_CLEAR, "Mode", "");
-               /* setting to set */
-       ot->prop= RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
+       /* flag-setting mode */
+       prop = RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_CLEAR, "Mode", "");
+       RNA_def_property_flag(prop, PROP_HIDDEN); /* internal hack - don't expose */
+       /* setting to set */
+       ot->prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
 }
 
-static void ANIM_OT_channels_setting_toggle (wmOperatorType *ot)
+static void ANIM_OT_channels_setting_toggle(wmOperatorType *ot)
 {
+       PropertyRNA *prop;
+       
        /* identifiers */
-       ot->name= "Toggle Channel Setting";
-       ot->idname= "ANIM_OT_channels_setting_toggle";
-       ot->description= "Toggle specified setting on all selected animation channels";
+       ot->name = "Toggle Channel Setting";
+       ot->idname = "ANIM_OT_channels_setting_toggle";
+       ot->description = "Toggle specified setting on all selected animation channels";
        
        /* api callbacks */
-       ot->invoke= WM_menu_invoke;
-       ot->exec= animchannels_setflag_exec;
-       ot->poll= animedit_poll_channels_active;
+       ot->invoke = WM_menu_invoke;
+       ot->exec = animchannels_setflag_exec;
+       ot->poll = animedit_poll_channels_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
        
        /* props */
-               /* flag-setting mode */
-       RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", "");
-               /* setting to set */
-       ot->prop= RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
+       /* flag-setting mode */
+       prop = RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", "");
+       RNA_def_property_flag(prop, PROP_HIDDEN); /* internal hack - don't expose */
+       /* setting to set */
+       ot->prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
 }
 
-static void ANIM_OT_channels_editable_toggle (wmOperatorType *ot)
+static void ANIM_OT_channels_editable_toggle(wmOperatorType *ot)
 {
+       PropertyRNA *prop;
+       
        /* identifiers */
-       ot->name= "Toggle Channel Editability";
-       ot->idname= "ANIM_OT_channels_editable_toggle";
-       ot->description= "Toggle editability of selected channels";
+       ot->name = "Toggle Channel Editability";
+       ot->idname = "ANIM_OT_channels_editable_toggle";
+       ot->description = "Toggle editability of selected channels";
        
        /* api callbacks */
-       ot->exec= animchannels_setflag_exec;
-       ot->poll= animedit_poll_channels_active;
+       ot->exec = animchannels_setflag_exec;
+       ot->poll = animedit_poll_channels_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
        
        /* props */
-               /* flag-setting mode */
+       /* flag-setting mode */
        RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", "");
-               /* setting to set */
-       RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, ACHANNEL_SETTING_PROTECT, "Type", "");
+       /* setting to set */
+       prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, ACHANNEL_SETTING_PROTECT, "Type", "");
+       RNA_def_property_flag(prop, PROP_HIDDEN); /* internal hack - don't expose */
 }
 
 /* ********************** Expand Channels Operator *********************** */
 
-static int animchannels_expand_exec (bContext *C, wmOperator *op)
+static int animchannels_expand_exec(bContext *C, wmOperator *op)
 {
        bAnimContext ac;
-       short onlysel= 1;
+       short onlysel = 1;
        
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -1629,41 +1904,41 @@ static int animchannels_expand_exec (bContext *C, wmOperator *op)
                
        /* only affect selected channels? */
        if (RNA_boolean_get(op->ptr, "all"))
-               onlysel= 0;
+               onlysel = 0;
        
        /* modify setting */
        setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_ADD, onlysel, 0);
        
        /* send notifier that things have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
        
        return OPERATOR_FINISHED;
 }
 
-static void ANIM_OT_channels_expand (wmOperatorType *ot)
+static void ANIM_OT_channels_expand(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Expand Channels";
-       ot->idname= "ANIM_OT_channels_expand";
-       ot->description= "Expand (i.e. open) all selected expandable animation channels";
+       ot->name = "Expand Channels";
+       ot->idname = "ANIM_OT_channels_expand";
+       ot->description = "Expand (i.e. open) all selected expandable animation channels";
        
        /* api callbacks */
-       ot->exec= animchannels_expand_exec;
-       ot->poll= animedit_poll_channels_active;
+       ot->exec = animchannels_expand_exec;
+       ot->poll = animedit_poll_channels_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
        
        /* props */
-       ot->prop= RNA_def_boolean(ot->srna, "all", 1, "All", "Expand all channels (not just selected ones)");
+       ot->prop = RNA_def_boolean(ot->srna, "all", 1, "All", "Expand all channels (not just selected ones)");
 }
 
 /* ********************** Collapse Channels Operator *********************** */
 
-static int animchannels_collapse_exec (bContext *C, wmOperator *op)
+static int animchannels_collapse_exec(bContext *C, wmOperator *op)
 {
        bAnimContext ac;
-       short onlysel= 1;
+       short onlysel = 1;
        
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -1671,43 +1946,43 @@ static int animchannels_collapse_exec (bContext *C, wmOperator *op)
                
        /* only affect selected channels? */
        if (RNA_boolean_get(op->ptr, "all"))
-               onlysel= 0;
+               onlysel = 0;
        
        /* modify setting */
        setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_CLEAR, onlysel, 0);
        
        /* send notifier that things have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
        
        return OPERATOR_FINISHED;
 }
 
-static void ANIM_OT_channels_collapse (wmOperatorType *ot)
+static void ANIM_OT_channels_collapse(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Collapse Channels";
-       ot->idname= "ANIM_OT_channels_collapse";
-       ot->description= "Collapse (i.e. close) all selected expandable animation channels";
+       ot->name = "Collapse Channels";
+       ot->idname = "ANIM_OT_channels_collapse";
+       ot->description = "Collapse (i.e. close) all selected expandable animation channels";
        
        /* api callbacks */
-       ot->exec= animchannels_collapse_exec;
-       ot->poll= animedit_poll_channels_active;
+       ot->exec = animchannels_collapse_exec;
+       ot->poll = animedit_poll_channels_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       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", 1, "All", "Collapse all channels (not just selected ones)");
 }
 
 /* ******************* Reenable Disabled Operator ******************* */
 
-static int animchannels_enable_poll (bContext *C)
+static int animchannels_enable_poll(bContext *C)
 {
-       ScrArea *sa= CTX_wm_area(C);
-       
+       ScrArea *sa = CTX_wm_area(C);
+
        /* channels region test */
-       // TODO: could enhance with actually testing if channels region?
+       /* TODO: could enhance with actually testing if channels region? */
        if (ELEM(NULL, sa, CTX_wm_region(C)))
                return 0;
                
@@ -1718,7 +1993,7 @@ static int animchannels_enable_poll (bContext *C)
        return 1;
 }
 
-static int animchannels_enable_exec (bContext *C, wmOperator *UNUSED(op))
+static int animchannels_enable_exec(bContext *C, wmOperator *UNUSED(op))
 {
        bAnimContext ac;
        
@@ -1731,11 +2006,11 @@ static int animchannels_enable_exec (bContext *C, wmOperator *UNUSED(op))
                return OPERATOR_CANCELLED;
        
        /* filter data */
-       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS);
+       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS);
        ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
        
        /* loop through filtered data and clean curves */
-       for (ale= anim_data.first; ale; ale= ale->next) {
+       for (ale = anim_data.first; ale; ale = ale->next) {
                FCurve *fcu = (FCurve *)ale->data;
                
                /* remove disabled flags from F-Curves */
@@ -1753,29 +2028,29 @@ static int animchannels_enable_exec (bContext *C, wmOperator *UNUSED(op))
        BLI_freelistN(&anim_data);
                
        /* send notifier that things have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
        
        return OPERATOR_FINISHED;
 }
 
-static void ANIM_OT_channels_fcurves_enable (wmOperatorType *ot)
+static void ANIM_OT_channels_fcurves_enable(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Revive Disabled F-Curves";
-       ot->idname= "ANIM_OT_channels_fcurves_enable";
-       ot->description= "Clears 'disabled' tag from all F-Curves to get broken F-Curves working again";
+       ot->name = "Revive Disabled F-Curves";
+       ot->idname = "ANIM_OT_channels_fcurves_enable";
+       ot->description = "Clears 'disabled' tag from all F-Curves to get broken F-Curves working again";
        
        /* api callbacks */
-       ot->exec= animchannels_enable_exec;
-       ot->poll= animchannels_enable_poll;
+       ot->exec = animchannels_enable_exec;
+       ot->poll = animchannels_enable_poll;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /* ********************** Select All Operator *********************** */
 
-static int animchannels_deselectall_exec (bContext *C, wmOperator *op)
+static int animchannels_deselectall_exec(bContext *C, wmOperator *op)
 {
        bAnimContext ac;
        
@@ -1790,39 +2065,39 @@ static int animchannels_deselectall_exec (bContext *C, wmOperator *op)
                ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, 1, ACHANNEL_SETFLAG_ADD);
        
        /* send notifier that things have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_SELECTED, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
        
        return OPERATOR_FINISHED;
 }
  
-static void ANIM_OT_channels_select_all_toggle (wmOperatorType *ot)
+static void ANIM_OT_channels_select_all_toggle(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Select All";
-       ot->idname= "ANIM_OT_channels_select_all_toggle";
-       ot->description= "Toggle selection of all animation channels";
+       ot->name = "Select All";
+       ot->idname = "ANIM_OT_channels_select_all_toggle";
+       ot->description = "Toggle selection of all animation channels";
        
        /* api callbacks */
-       ot->exec= animchannels_deselectall_exec;
-       ot->poll= animedit_poll_channels_nla_tweakmode_off;
+       ot->exec = animchannels_deselectall_exec;
+       ot->poll = animedit_poll_channels_nla_tweakmode_off;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       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", 0, "Invert", "");
 }
 
 /* ******************** Borderselect Operator *********************** */
 
-static void borderselect_anim_channels (bAnimContext *ac, rcti *rect, short selectmode)
+static void borderselect_anim_channels(bAnimContext *ac, rcti *rect, short selectmode)
 {
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
        int filter;
        
        SpaceNla *snla = (SpaceNla *)ac->sl;
-       View2D *v2d= &ac->ar->v2d;
+       View2D *v2d = &ac->ar->v2d;
        rctf rectf;
        float ymin, ymax;
        
@@ -1837,19 +2112,19 @@ static void borderselect_anim_channels (bAnimContext *ac, rcti *rect, short sele
        }
        
        /* convert border-region to view coordinates */
-       UI_view2d_region_to_view(v2d, rect->xmin, rect->ymin+2, &rectf.xmin, &rectf.ymin);
-       UI_view2d_region_to_view(v2d, rect->xmax, rect->ymax-2, &rectf.xmax, &rectf.ymax);
+       UI_view2d_region_to_view(v2d, rect->xmin, rect->ymin + 2, &rectf.xmin, &rectf.ymin);
+       UI_view2d_region_to_view(v2d, rect->xmax, rect->ymax - 2, &rectf.xmax, &rectf.ymax);
        
        /* filter data */
-       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* loop over data, doing border select */
-       for (ale= anim_data.first; ale; ale= ale->next) {
+       for (ale = anim_data.first; ale; ale = ale->next) {
                if (ac->datatype == ANIMCONT_NLA)
-                       ymin= ymax - NLACHANNEL_STEP(snla);
+                       ymin = ymax - NLACHANNEL_STEP(snla);
                else
-                       ymin= ymax - ACHANNEL_STEP;
+                       ymin = ymax - ACHANNEL_STEP;
                
                /* if channel is within border-select region, alter it */
                if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
@@ -1860,27 +2135,27 @@ static void borderselect_anim_channels (bAnimContext *ac, rcti *rect, short sele
                        switch (ale->type) {
                                case ANIMTYPE_GROUP:
                                {
-                                       bActionGroup *agrp= (bActionGroup *)ale->data;
+                                       bActionGroup *agrp = (bActionGroup *)ale->data;
                                        
                                        /* always clear active flag after doing this */
                                        agrp->flag &= ~AGRP_ACTIVE;
                                }
-                                       break;
+                               break;
                                case ANIMTYPE_NLATRACK:
                                {
-                                       NlaTrack *nlt= (NlaTrack *)ale->data;
+                                       NlaTrack *nlt = (NlaTrack *)ale->data;
                                        
                                        /* for now, it's easier just to do this here manually, as defining a new type 
                                         * currently adds complications when doing other stuff 
                                         */
                                        ACHANNEL_SET_FLAG(nlt, selectmode, NLATRACK_SELECTED);
                                }
-                                       break;
+                               break;
                        }
                }
                
                /* set minimum extent to be the maximum of the next channel */
-               ymax= ymin;
+               ymax = ymin;
        }
        
        /* cleanup */
@@ -1893,7 +2168,7 @@ static int animchannels_borderselect_exec(bContext *C, wmOperator *op)
 {
        bAnimContext ac;
        rcti rect;
-       short selectmode=0;
+       short selectmode = 0;
        int gesture_mode, extend;
        
        /* get editor data */
@@ -1901,15 +2176,12 @@ static int animchannels_borderselect_exec(bContext *C, wmOperator *op)
                return OPERATOR_CANCELLED;
        
        /* get settings from operator */
-       rect.xmin= RNA_int_get(op->ptr, "xmin");
-       rect.ymin= RNA_int_get(op->ptr, "ymin");
-       rect.xmax= RNA_int_get(op->ptr, "xmax");
-       rect.ymax= RNA_int_get(op->ptr, "ymax");
+       WM_operator_properties_border_to_rcti(op, &rect);
        
-       gesture_mode= RNA_int_get(op->ptr, "gesture_mode");
-       extend= RNA_boolean_get(op->ptr, "extend");
+       gesture_mode = RNA_int_get(op->ptr, "gesture_mode");
+       extend = RNA_boolean_get(op->ptr, "extend");
 
-       if(!extend)
+       if (!extend)
                ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, 1, ACHANNEL_SETFLAG_CLEAR);
 
        if (gesture_mode == GESTURE_MODAL_SELECT)
@@ -1921,7 +2193,7 @@ static int animchannels_borderselect_exec(bContext *C, wmOperator *op)
        borderselect_anim_channels(&ac, &rect, selectmode);
        
        /* send notifier that things have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_SELECTED, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
        
        return OPERATOR_FINISHED;
 } 
@@ -1929,20 +2201,20 @@ static int animchannels_borderselect_exec(bContext *C, wmOperator *op)
 static void ANIM_OT_channels_select_border(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Border Select";
-       ot->idname= "ANIM_OT_channels_select_border";
-       ot->description= "Select all animation channels within the specified region";
+       ot->name = "Border Select";
+       ot->idname = "ANIM_OT_channels_select_border";
+       ot->description = "Select all animation channels within the specified region";
        
        /* api callbacks */
-       ot->invoke= WM_border_select_invoke;
-       ot->exec= animchannels_borderselect_exec;
-       ot->modal= WM_border_select_modal;
-       ot->cancel= WM_border_select_cancel;
+       ot->invoke = WM_border_select_invoke;
+       ot->exec = animchannels_borderselect_exec;
+       ot->modal = WM_border_select_modal;
+       ot->cancel = WM_border_select_cancel;
        
-       ot->poll= animedit_poll_channels_nla_tweakmode_off;
+       ot->poll = animedit_poll_channels_nla_tweakmode_off;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
        
        /* rna */
        WM_operator_properties_gesture_border(ot, TRUE);
@@ -1951,7 +2223,7 @@ static void ANIM_OT_channels_select_border(wmOperatorType *ot)
 /* ******************* Rename Operator ***************************** */
 /* Allow renaming some channels by clicking on them */
 
-static void rename_anim_channels (bAnimContext *ac, int channel_index)
+static void rename_anim_channels(bAnimContext *ac, int channel_index)
 {
        ListBase anim_data = {NULL, NULL};
        bAnimChannelType *acf;
@@ -1959,16 +2231,16 @@ static void rename_anim_channels (bAnimContext *ac, int channel_index)
        int filter;
        
        /* get the channel that was clicked on */
-               /* filter channels */
-       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+       /* 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);
+       /* get channel from index */
+       ale = BLI_findlink(&anim_data, channel_index);
        if (ale == NULL) {
                /* channel not found */
-               if (G.f & G_DEBUG)
-                       printf("Error: animation channel (index = %d) not found in rename_anim_channels() \n", 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;
@@ -2000,7 +2272,7 @@ static void rename_anim_channels (bAnimContext *ac, int channel_index)
        ED_region_tag_redraw(ac->ar);
 }
 
-static int animchannels_rename_invoke (bContext *C, wmOperator *UNUSED(op), wmEvent *evt)
+static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *evt)
 {
        bAnimContext ac;
        ARegion *ar;
@@ -2013,11 +2285,11 @@ static int animchannels_rename_invoke (bContext *C, wmOperator *UNUSED(op), wmEv
                return OPERATOR_CANCELLED;
                
        /* get useful pointers from animation context data */
-       ar= ac.ar;
-       v2d= &ar->v2d;
+       ar = ac.ar;
+       v2d = &ar->v2d;
        
        /* figure out which channel user clicked in 
-        * Note: although channels technically start at y= ACHANNEL_FIRST, we need to adjust by half a channel's height
+        * Note: although channels technically start at (y = ACHANNEL_FIRST), we need to adjust by half a channel's height
         *              so that the tops of channels get caught ok. Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use
         *              ACHANNEL_HEIGHT_HALF.
         */
@@ -2037,22 +2309,22 @@ static int animchannels_rename_invoke (bContext *C, wmOperator *UNUSED(op), wmEv
        return OPERATOR_FINISHED;
 }
 
-static void ANIM_OT_channels_rename (wmOperatorType *ot)
+static void ANIM_OT_channels_rename(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Rename Channels";
-       ot->idname= "ANIM_OT_channels_rename";
-       ot->description= "Rename animation channel under mouse";
+       ot->name = "Rename Channels";
+       ot->idname = "ANIM_OT_channels_rename";
+       ot->description = "Rename animation channel under mouse";
        
        /* api callbacks */
-       ot->invoke= animchannels_rename_invoke;
-       ot->poll= animedit_poll_channels_active;
+       ot->invoke = animchannels_rename_invoke;
+       ot->poll = animedit_poll_channels_active;
 }
 
 /* ******************** 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(bAnimContext *ac, float UNUSED(x), int channel_index, short selectmode)
 {
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
@@ -2060,36 +2332,36 @@ static int mouse_anim_channels (bAnimContext *ac, float UNUSED(x), int channel_i
        int notifierFlags = 0;
        
        /* get the channel that was clicked on */
-               /* filter channels */
-       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+       /* 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);
+       /* get channel from index */
+       ale = BLI_findlink(&anim_data, channel_index);
        if (ale == NULL) {
                /* channel not found */
-               if (G.f & G_DEBUG)
-                       printf("Error: animation channel (index = %d) not found in mouse_anim_channels() \n", channel_index);
+               if (G.debug & G_DEBUG)
+                       printf("Error: animation channel (index = %d) not found in mouse_anim_channels()\n", channel_index);
                
                BLI_freelistN(&anim_data);
                return 0;
        }
-       
+
        /* selectmode -1 is a special case for ActionGroups only, which selects all of the channels underneath it only... */
-       // TODO: should this feature be extended to work with other channel types too?
+       /* 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);
                return 0;
        }
-       
+
        /* action to take depends on what channel we've got */
-       // WARNING: must keep this in sync with the equivalent function in nla_channels.c
+       /* WARNING: must keep this in sync with the equivalent function in nla_channels.c */
        switch (ale->type) {
                case ANIMTYPE_SCENE:
                {
-                       Scene *sce= (Scene *)ale->data;
-                       AnimData *adt= sce->adt;
+                       Scene *sce = (Scene *)ale->data;
+                       AnimData *adt = sce->adt;
                        
                        /* set selection status */
                        if (selectmode == SELECT_INVERT) {
@@ -2102,22 +2374,22 @@ static int mouse_anim_channels (bAnimContext *ac, float UNUSED(x), int channel_i
                                if (adt) adt->flag |= ADT_UI_SELECTED;
                        }
                        
-                       notifierFlags |= (ND_ANIMCHAN|NA_SELECTED);
+                       notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
                }
-                       break;
+               break;
                case ANIMTYPE_OBJECT:
                {
-                       bDopeSheet *ads= (bDopeSheet *)ac->data;
-                       Scene *sce= (Scene *)ads->source;
-                       Base *base= (Base *)ale->data;
-                       Object *ob= base->object;
-                       AnimData *adt= ob->adt;
+                       bDopeSheet *ads = (bDopeSheet *)ac->data;
+                       Scene *sce = (Scene *)ads->source;
+                       Base *base = (Base *)ale->data;
+                       Object *ob = base->object;
+                       AnimData *adt = ob->adt;
                        
                        /* set selection status */
                        if (selectmode == SELECT_INVERT) {
                                /* swap select */
                                base->flag ^= SELECT;
-                               ob->flag= base->flag;
+                               ob->flag = base->flag;
                                
                                if (adt) adt->flag ^= ADT_UI_SELECTED;
                        }
@@ -2125,11 +2397,11 @@ static int mouse_anim_channels (bAnimContext *ac, float UNUSED(x), int channel_i
                                Base *b;
                                
                                /* deselect all */
-                               // TODO: should this deselect all other types of channels too?
-                               for (b= sce->base.first; b; b= b->next) {
+                               /* TODO: should this deselect all other types of channels too? */
+                               for (b = sce->base.first; b; b = b->next) {
                                        b->flag &= ~SELECT;
-                                       b->object->flag= b->flag;
-                                       if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED|ADT_UI_ACTIVE);
+                                       b->object->flag = b->flag;
+                                       if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE);
                                }
                                
                                /* select object now */
@@ -2141,12 +2413,12 @@ static int mouse_anim_channels (bAnimContext *ac, float UNUSED(x), int channel_i
                        if ((adt) && (adt->flag & ADT_UI_SELECTED))
                                adt->flag |= ADT_UI_ACTIVE;
                        
-                       notifierFlags |= (ND_ANIMCHAN|NA_SELECTED);
+                       notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
                }
-                       break;
+               break;
                
                case ANIMTYPE_FILLACTD: /* Action Expander */
-               case ANIMTYPE_DSMAT:    /* Datablock AnimData Expanders */
+               case ANIMTYPE_DSMAT:    /* Datablock AnimData Expanders */
                case ANIMTYPE_DSLAM:
                case ANIMTYPE_DSCAM:
                case ANIMTYPE_DSCUR:
@@ -2159,6 +2431,9 @@ static int mouse_anim_channels (bAnimContext *ac, float UNUSED(x), int channel_i
                case ANIMTYPE_DSNTREE:
                case ANIMTYPE_DSTEX:
                case ANIMTYPE_DSLAT:
+#ifdef WITH_FREESTYLE
+               case ANIMTYPE_DSLINESTYLE:
+#endif
                case ANIMTYPE_DSSPK:
                {
                        /* sanity checking... */
@@ -2179,13 +2454,13 @@ static int mouse_anim_channels (bAnimContext *ac, float UNUSED(x), int channel_i
                                        ale->adt->flag |= ADT_UI_ACTIVE;
                        }
                        
-                       notifierFlags |= (ND_ANIMCHAN|NA_SELECTED);
-               }       
-                       break;
+                       notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
+               }
+               break;
                
                case ANIMTYPE_GROUP: 
                {
-                       bActionGroup *agrp= (bActionGroup *)ale->data;
+                       bActionGroup *agrp = (bActionGroup *)ale->data;
                        
                        /* select/deselect group */
                        if (selectmode == SELECT_INVERT) {
@@ -2193,16 +2468,16 @@ static int mouse_anim_channels (bAnimContext *ac, float UNUSED(x), int channel_i
                                agrp->flag ^= AGRP_SELECTED;
                        }
                        else if (selectmode == -1) {
-                               /* select all in group (and deselect everthing else) */ 
+                               /* select all in group (and deselect everthing else) */
                                FCurve *fcu;
                                
                                /* deselect all other channels */
                                ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
                                
                                /* only select channels in group and group itself */
-                               for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next)
+                               for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcu->next)
                                        fcu->flag |= FCURVE_SELECTED;
-                               agrp->flag |= AGRP_SELECTED;                                    
+                               agrp->flag |= AGRP_SELECTED;
                        }
                        else {
                                /* select group by itself */
@@ -2213,13 +2488,15 @@ static int mouse_anim_channels (bAnimContext *ac, float UNUSED(x), int channel_i
                        /* if group is selected now, make group the 'active' one in the visible list */
                        if (agrp->flag & AGRP_SELECTED)
                                ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
+                       else
+                               ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, NULL, ANIMTYPE_GROUP);
                                
-                       notifierFlags |= (ND_ANIMCHAN|NA_SELECTED);
+                       notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
                }
-                       break;
+               break;
                case ANIMTYPE_FCURVE: 
                {
-                       FCurve *fcu= (FCurve *)ale->data;
+                       FCurve *fcu = (FCurve *)ale->data;
                        
                        /* select/deselect */
                        if (selectmode == SELECT_INVERT) {
@@ -2236,12 +2513,12 @@ static int mouse_anim_channels (bAnimContext *ac, float UNUSED(x), int channel_i
                        if (fcu->flag & FCURVE_SELECTED)
                                ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
                                
-                       notifierFlags |= (ND_ANIMCHAN|NA_SELECTED);
+                       notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
                }
-                       break;
+               break;
                case ANIMTYPE_SHAPEKEY: 
                {
-                       KeyBlock *kb= (KeyBlock *)ale->data;
+                       KeyBlock *kb = (KeyBlock *)ale->data;
                        
                        /* select/deselect */
                        if (selectmode == SELECT_INVERT) {
@@ -2254,42 +2531,72 @@ static int mouse_anim_channels (bAnimContext *ac, float UNUSED(x), int channel_i
                                kb->flag |= KEYBLOCK_SEL;
                        }
                                
-                       notifierFlags |= (ND_ANIMCHAN|NA_SELECTED);
+                       notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
                }
-                       break;
+               break;
                case ANIMTYPE_GPDATABLOCK:
                {
-                       bGPdata *gpd= (bGPdata *)ale->data;
+                       bGPdata *gpd = (bGPdata *)ale->data;
                        
                        /* toggle expand 
                         *      - although the triangle widget already allows this, the whole channel can also be used for this purpose
                         */
                        gpd->flag ^= GP_DATA_EXPAND;
                        
-                       notifierFlags |= (ND_ANIMCHAN|NA_EDITED);
+                       notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
                }
-                       break;
+               break;
                case ANIMTYPE_GPLAYER:
                {
-                       bGPDlayer *gpl= (bGPDlayer *)ale->data;
+                       bGPDlayer *gpl = (bGPDlayer *)ale->data;
                        
                        /* select/deselect */
                        if (selectmode == SELECT_INVERT) {
                                /* invert selection status of this layer only */
                                gpl->flag ^= GP_LAYER_SELECT;
                        }
-                       else {  
+                       else {
                                /* select layer by itself */
                                ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
                                gpl->flag |= GP_LAYER_SELECT;
                        }
                        
-                       notifierFlags |= (ND_ANIMCHAN|NA_EDITED);
+                       notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
                }
-                       break;
+               break;
+               case ANIMTYPE_MASKDATABLOCK:
+               {
+                       Mask *mask = (Mask *)ale->data;
+                       
+                       /* toggle expand
+                        *      - although the triangle widget already allows this, the whole channel can also be used for this purpose
+                        */
+                       mask->flag ^= MASK_ANIMF_EXPAND;
+                       
+                       notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
+               }
+               break;
+               case ANIMTYPE_MASKLAYER:
+               {
+                       MaskLayer *masklay = (MaskLayer *)ale->data;
+                       
+                       /* select/deselect */
+                       if (selectmode == SELECT_INVERT) {
+                               /* invert selection status of this layer only */
+                               masklay->flag ^= MASK_LAYERFLAG_SELECT;
+                       }
+                       else {
+                               /* select layer by itself */
+                               ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+                               masklay->flag |= MASK_LAYERFLAG_SELECT;
+                       }
+                       
+                       notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
+               }
+               break;
                default:
-                       if (G.f & G_DEBUG)
-                               printf("Error: Invalid channel type in mouse_anim_channels() \n");
+                       if (G.debug & G_DEBUG)
+                               printf("Error: Invalid channel type in mouse_anim_channels()\n");
        }
        
        /* free channels */
@@ -2318,19 +2625,19 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *
                return OPERATOR_CANCELLED;
                
        /* get useful pointers from animation context data */
-       ar= ac.ar;
-       v2d= &ar->v2d;
+       ar = ac.ar;
+       v2d = &ar->v2d;
        
        /* select mode is either replace (deselect all, then add) or add/extend */
        if (RNA_boolean_get(op->ptr, "extend"))
-               selectmode= SELECT_INVERT;
+               selectmode = SELECT_INVERT;
        else if (RNA_boolean_get(op->ptr, "children_only"))
-               selectmode= -1; /* this is a bit of a special case for ActionGroups only... should it be removed or extended to all instead? */
+               selectmode = -1;  /* this is a bit of a special case for ActionGroups only... should it be removed or extended to all instead? */
        else
-               selectmode= SELECT_REPLACE;
+               selectmode = SELECT_REPLACE;
        
        /* figure out which channel user clicked in 
-        * Note: although channels technically start at y= ACHANNEL_FIRST, we need to adjust by half a channel's height
+        * Note: although channels technically start at (y = ACHANNEL_FIRST), we need to adjust by half a channel's height
         *              so that the tops of channels get caught ok. Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use
         *              ACHANNEL_HEIGHT_HALF.
         */
@@ -2338,31 +2645,37 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *
        UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP, 0, (float)ACHANNEL_HEIGHT_HALF, 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(&ac, x, channel_index, selectmode);
        
        /* set notifier that things have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|notifierFlags, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | notifierFlags, NULL);
        
        return OPERATOR_FINISHED;
 }
  
-static void ANIM_OT_channels_click (wmOperatorType *ot)
+static void ANIM_OT_channels_click(wmOperatorType *ot)
 {
+       PropertyRNA *prop;
+       
        /* identifiers */
-       ot->name= "Mouse Click on Channels";
-       ot->idname= "ANIM_OT_channels_click";
-       ot->description= "Handle mouse-clicks over animation channels";
+       ot->name = "Mouse Click on Channels";
+       ot->idname = "ANIM_OT_channels_click";
+       ot->description = "Handle mouse-clicks over animation channels";
        
        /* api callbacks */
-       ot->invoke= animchannels_mouseclick_invoke;
-       ot->poll= animedit_poll_channels_active;
+       ot->invoke = animchannels_mouseclick_invoke;
+       ot->poll = animedit_poll_channels_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
        
-       /* id-props */
-       RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
-       RNA_def_boolean(ot->srna, "children_only", 0, "Select Children Only", ""); // CTRLKEY|SHIFTKEY
+       /* 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
+       RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+       
+       prop = RNA_def_boolean(ot->srna, "children_only", 0, "Select Children Only", ""); // CTRLKEY|SHIFTKEY
+       RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 }
 
 /* ************************************************************************** */
@@ -2379,10 +2692,10 @@ void ED_operatortypes_animchannels(void)
        WM_operatortype_append(ANIM_OT_channels_setting_enable);
        WM_operatortype_append(ANIM_OT_channels_setting_disable);
        WM_operatortype_append(ANIM_OT_channels_setting_toggle);
-       
+
        WM_operatortype_append(ANIM_OT_channels_delete);
-       
-               // XXX does this need to be a separate operator?
+
+       /* XXX does this need to be a separate operator? */
        WM_operatortype_append(ANIM_OT_channels_editable_toggle);
        
        WM_operatortype_append(ANIM_OT_channels_move);
@@ -2394,6 +2707,9 @@ void ED_operatortypes_animchannels(void)
        WM_operatortype_append(ANIM_OT_channels_visibility_set);
        
        WM_operatortype_append(ANIM_OT_channels_fcurves_enable);
+       
+       WM_operatortype_append(ANIM_OT_channels_group);
+       WM_operatortype_append(ANIM_OT_channels_ungroup);
 }
 
 // TODO: check on a poll callback for this, to get hotkeys into menus
@@ -2403,20 +2719,20 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
        wmKeyMapItem *kmi;
 
        /* selection */
-               /* click-select */
-               // XXX for now, only leftmouse.... 
+       /* 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);
-       
-               /* rename */
+       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);
        
-               /* deselect all */
+       /* 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);
        
-               /* borderselect */
+       /* borderselect */
        WM_keymap_add_item(keymap, "ANIM_OT_channels_select_border", BKEY, KM_PRESS, 0, 0);
        WM_keymap_add_item(keymap, "ANIM_OT_channels_select_border", EVT_TWEAK_L, KM_ANY, 0, 0);
        
@@ -2426,7 +2742,7 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
        
        /* settings */
        WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_toggle", WKEY, KM_PRESS, KM_SHIFT, 0);
-       WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_enable", WKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
+       WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_enable", WKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
        WM_keymap_add_item(keymap, "ANIM_OT_channels_setting_disable", WKEY, KM_PRESS, KM_ALT, 0);
        
        /* settings - specialized hotkeys */
@@ -2447,6 +2763,10 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
        RNA_enum_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_move", PAGEUPKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "direction", REARRANGE_ANIMCHAN_TOP);
        RNA_enum_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_move", PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "direction", REARRANGE_ANIMCHAN_BOTTOM);
        
+       /* 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);