Bugfix #20664: NLA Editor - Hiding stuff causes instant crash ..
[blender.git] / source / blender / editors / animation / anim_channels_edit.c
index 1e5f1eac8674355134210b8458662fb06489b472..f756c5b3158640025e37b1ed4f0a92271c975af8 100644 (file)
@@ -37,7 +37,7 @@
 #include "MEM_guardedalloc.h"
 
 #include "BLI_blenlib.h"
-#include "BLI_arithb.h"
+#include "BLI_math.h"
 
 #include "DNA_listBase.h"
 #include "DNA_anim_types.h"
@@ -86,9 +86,9 @@
 #include "WM_types.h"
 
 /* ************************************************************************** */
-/* CHANNELS API */
+/* CHANNELS API - Exposed API */
 
-/* -------------------------- Exposed API ----------------------------------- */
+/* -------------------------- Selection ------------------------------------- */
 
 /* Set the given animation-channel as the active one for the active context */
 // TODO: extend for animdata types...
@@ -142,6 +142,7 @@ void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int
                        case ANIMTYPE_DSPART:
                        case ANIMTYPE_DSMBALL:
                        case ANIMTYPE_DSARM:
+                       case ANIMTYPE_DSMESH:
                        {
                                /* need to verify that this data is valid for now */
                                if (ale->adt) {
@@ -184,6 +185,7 @@ void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int
                        case ANIMTYPE_DSPART:
                        case ANIMTYPE_DSMBALL:
                        case ANIMTYPE_DSARM:
+                       case ANIMTYPE_DSMESH:
                        {
                                /* need to verify that this data is valid for now */
                                if (ale->adt)
@@ -203,7 +205,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 (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;
@@ -211,7 +213,7 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short
        
        /* filter data */
        filter= ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS;
-       ANIM_animdata_filter(NULL, &anim_data, filter, data, datatype);
+       ANIM_animdata_filter(ac, &anim_data, filter, data, datatype);
        
        /* See if we should be selecting or deselecting */
        if (test) {
@@ -257,6 +259,7 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short
                                case ANIMTYPE_DSPART:
                                case ANIMTYPE_DSMBALL:
                                case ANIMTYPE_DSARM:
+                               case ANIMTYPE_DSMESH:
                                {
                                        if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED))
                                                sel= ACHANNEL_SETFLAG_CLEAR;
@@ -337,6 +340,7 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short
                        case ANIMTYPE_DSPART:
                        case ANIMTYPE_DSMBALL:
                        case ANIMTYPE_DSARM:
+                       case ANIMTYPE_DSMESH:
                        {
                                /* need to verify that this data is valid for now */
                                if (ale->adt) {
@@ -352,6 +356,164 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short
        BLI_freelistN(&anim_data);
 }
 
+/* ---------------------------- Graph Editor ------------------------------------- */
+
+/* Flush visibility (for Graph Editor) changes up/down hierarchy for changes in the given setting 
+ *     - anim_data: list of the all the anim channels that can be chosen
+ *             -> filtered using ANIMFILTER_CHANNELS only, since if we took VISIBLE too,
+ *               then the channels under closed expanders get ignored...
+ *     - ale_setting: the anim channel (not in the anim_data list directly, though occuring there)
+ *             with the new state of the setting that we want flushed up/down the hierarchy 
+ *     - 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)
+{
+       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) {
+               /* 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?
+                       if (ale->id == ale_setting->id) {
+                               match= ale;
+                               break;
+                       }
+               }
+       }
+       if (match == NULL) {
+               printf("ERROR: no channel matching the one changed was found \n");
+               return;
+       }
+       else {
+               bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale_setting);
+               
+               if (acf == NULL) {
+                       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
+                */
+               matchLevel= (acf->get_offset)? acf->get_offset(ac, ale_setting) : 0;
+               prevLevel= matchLevel;
+       }
+       
+       /* flush up? 
+        *
+        * For Visibility:
+        *      - only flush up if the current state is now enabled (positive 'on' state is default) 
+        *        (otherwise, it's too much work to force the parents to be inactive too)
+        *
+        * For everything else:
+        *      - only flush up if the current state is now disabled (negative 'off' state is default)
+        *        (otherwise, it's too much work to force the parents to be active too)
+        */
+       if ( ((setting == ACHANNEL_SETTING_VISIBLE) && on) ||
+                ((setting != ACHANNEL_SETTING_VISIBLE) && on==0) )
+       {
+               /* 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);
+                       int level;
+                       
+                       /* if no channel info was found, skip, since this type might not have any useful info */
+                       if (acf == NULL)
+                               continue;
+                       
+                       /* get the level of the current channel traversed 
+                        *       - 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;
+                       
+                       /* 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, 
+                        * when toggling visibility of F-Curves, gets flushed), flush the new status...
+                        */
+                       if (level < prevLevel)
+                               ANIM_channel_setting_set(ac, ale, setting, on);
+                       /* however, if the level is 'greater than' (i.e. less important than the previous channel,
+                        * stop searching, since we've already reached the bottom of another hierarchy
+                        */
+                       else if (level > matchLevel)
+                               break;
+                       
+                       /* store this level as the 'old' level now */
+                       prevLevel= level;
+               }
+       }
+       
+       /* 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);
+                       int level;
+                       
+                       /* if no channel info was found, skip, since this type might not have any useful info */
+                       if (acf == NULL)
+                               continue;
+                       
+                       /* get the level of the current channel traversed 
+                        *       - 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;
+                       
+                       /* if the level is 'greater than' (i.e. less important) the channel that was changed, 
+                        * flush the new status...
+                        */
+                       if (level > matchLevel)
+                               ANIM_channel_setting_set(ac, ale, setting, on);
+                       /* however, if the level is 'less than or equal to' the channel that was changed,
+                        * (i.e. the current channel is as important if not more important than the changed channel)
+                        * then we should stop, since we've found the last one of the children we should flush
+                        */
+                       else
+                               break;
+                       
+                       /* store this level as the 'old' level now */
+                       prevLevel= level;
+               }
+       }
+}
+
+/* -------------------------- F-Curves ------------------------------------- */
+
+/* Delete the given F-Curve from its AnimData block */
+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
+        * - if no F-Curve, there is nothing to remove
+        */
+       if (ELEM(NULL, adt, fcu))
+               return;
+               
+       /* remove from whatever list it came from
+        *      - Action Group
+        *      - Action
+        *      - Drivers
+        *      - TODO... some others?
+        */
+       if (fcu->grp)
+               action_groups_remove_channel(adt->action, fcu);
+       else if ((ac) && (ac->datatype == ANIMCONT_DRIVERS))
+               BLI_remlink(&adt->drivers, fcu);
+       else if (adt->action)
+               BLI_remlink(&adt->action->curves, fcu);
+               
+       /* free the F-Curve itself */
+       free_fcurve(fcu);
+}
+
 /* ************************************************************************** */
 /* OPERATORS */
 
@@ -845,25 +1007,8 @@ static int animchannels_delete_exec(bContext *C, wmOperator *op)
                                AnimData *adt= ale->adt;
                                FCurve *fcu= (FCurve *)ale->data;
                                
-                               /* if no AnimData, we've got nowhere to remove the F-Curve from */
-                               if (adt == NULL)
-                                       continue;
-                                       
-                               /* remove from whatever list it came from
-                                *      - Action Group
-                                *      - Action
-                                *      - Drivers
-                                *      - TODO... some others?
-                                */
-                               if (fcu->grp)
-                                       action_groups_remove_channel(adt->action, fcu);
-                               else if (adt->action)
-                                       BLI_remlink(&adt->action->curves, fcu);
-                               else if (ac.datatype == ANIMCONT_DRIVERS)
-                                       BLI_remlink(&adt->drivers, fcu);
-                                       
-                               /* free the F-Curve itself */
-                               free_fcurve(fcu);
+                               /* try to free F-Curve */
+                               ANIM_fcurve_delete_from_animdata(&ac, adt, fcu);
                        }
                }
                
@@ -892,12 +1037,87 @@ void ANIM_OT_channels_delete (wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
+/* ******************** Set Channel Visibility Operator *********************** */
+/* NOTE: this operator is only valid in the Graph Editor channels region */
+
+static int animchannels_visibility_set_exec(bContext *C, wmOperator *op)
+{
+       bAnimContext ac;
+       ListBase anim_data = {NULL, NULL};
+       ListBase all_data = {NULL, NULL};
+       bAnimListElem *ale;
+       int filter;
+       
+       /* get editor data */
+       if (ANIM_animdata_get_context(C, &ac) == 0)
+               return OPERATOR_CANCELLED;
+       
+       
+       /* hide all channels not selected */
+       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_UNSEL);
+       ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+       
+       for (ale= anim_data.first; ale; ale= ale->next)
+               ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR);
+       
+       BLI_freelistN(&anim_data);
+       
+       
+       /* get list of all channels that selection may need to be flushed to */
+       filter= ANIMFILTER_CHANNELS;
+       ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
+       
+       /* make all the selected channels visible */
+       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL);
+       ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+       
+       for (ale= anim_data.first; ale; ale= ale->next) {
+               /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
+               // TODO: find out why this is the case, and fix that
+               if (ale->type == ANIMTYPE_OBJECT)
+                       continue;
+               
+               /* enable the setting */
+               ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
+               
+               /* now, also flush selection status up/down as appropriate */
+               ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, 1);
+       }
+       
+       BLI_freelistN(&anim_data);
+       BLI_freelistN(&all_data);
+       
+       
+       /* send notifier that things have changed */
+       WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
+       
+       return OPERATOR_FINISHED;
+}
+
+void ANIM_OT_channels_visibility_set (wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Set Visibility";
+       ot->idname= "ANIM_OT_channels_visibility_set";
+       ot->description= "Make only the selected animation channels visible in the Graph Editor.";
+       
+       /* api callbacks */
+       ot->exec= animchannels_visibility_set_exec;
+       ot->poll= ED_operator_ipo_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
 /* ******************** Toggle Channel Visibility Operator *********************** */
+/* NOTE: this operator is only valid in the Graph Editor channels region */
 
 static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *op)
 {
        bAnimContext ac;
        ListBase anim_data = {NULL, NULL};
+       ListBase all_data = {NULL, NULL};
        bAnimListElem *ale;
        int filter;
        short vis= ACHANNEL_SETFLAG_ADD;
@@ -906,6 +1126,10 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *op)
        if (ANIM_animdata_get_context(C, &ac) == 0)
                return OPERATOR_CANCELLED;
                
+       /* get list of all channels that selection may need to be flushed to */
+       filter= ANIMFILTER_CHANNELS;
+       ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
+               
        /* filter data */
        filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL);
        ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
@@ -919,14 +1143,24 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *op)
                if (ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_VISIBLE))
                        vis= ACHANNEL_SETFLAG_CLEAR;
        }
-               
+
        /* Now set the flags */
        for (ale= anim_data.first; ale; ale= ale->next) {
+               /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
+               // TODO: find out why this is the case, and fix that
+               if (ale->type == ANIMTYPE_OBJECT)
+                       continue;
+               
+               /* change the setting */
                ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, vis);
+               
+               /* now, also flush selection status up/down as appropriate */
+               ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, (vis == ACHANNEL_SETFLAG_ADD));
        }
        
        /* cleanup */
        BLI_freelistN(&anim_data);
+       BLI_freelistN(&all_data);
        
        /* send notifier that things have changed */
        WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
@@ -1043,7 +1277,7 @@ void ANIM_OT_channels_setting_enable (wmOperatorType *ot)
                /* flag-setting mode */
        RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_ADD, "Mode", "");
                /* setting to set */
-       RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
+       ot->prop= RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
 }
 
 void ANIM_OT_channels_setting_disable (wmOperatorType *ot)
@@ -1065,7 +1299,7 @@ void ANIM_OT_channels_setting_disable (wmOperatorType *ot)
                /* flag-setting mode */
        RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_CLEAR, "Mode", "");
                /* setting to set */
-       RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
+       ot->prop= RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
 }
 
 void ANIM_OT_channels_setting_toggle (wmOperatorType *ot)
@@ -1087,7 +1321,7 @@ void ANIM_OT_channels_setting_toggle (wmOperatorType *ot)
                /* 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, 0, "Type", "");
+       ot->prop= RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
 }
 
 // XXX currently, this is a separate operator, but perhaps we could in future specify in keymaps whether to call invoke or exec?
@@ -1151,7 +1385,7 @@ void ANIM_OT_channels_expand (wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
        /* props */
-       RNA_def_boolean(ot->srna, "all", 0, "All", "Expand all channels (not just selected ones)");
+       RNA_def_boolean(ot->srna, "all", 1, "All", "Expand all channels (not just selected ones)");
 }
 
 /* ********************** Collapse Channels Operator *********************** */
@@ -1193,7 +1427,7 @@ void ANIM_OT_channels_collapse (wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
        /* props */
-       RNA_def_boolean(ot->srna, "all", 0, "All", "Collapse all channels (not just selected ones)");
+       RNA_def_boolean(ot->srna, "all", 1, "All", "Collapse all channels (not just selected ones)");
 }
 
 /* ********************** Select All Operator *********************** */
@@ -1208,9 +1442,9 @@ static int animchannels_deselectall_exec(bContext *C, wmOperator *op)
                
        /* 'standard' behaviour - check if selected, then apply relevant selection */
        if (RNA_boolean_get(op->ptr, "invert"))
-               ANIM_deselect_anim_channels(ac.data, ac.datatype, 0, ACHANNEL_SETFLAG_TOGGLE);
+               ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, 0, ACHANNEL_SETFLAG_TOGGLE);
        else
-               ANIM_deselect_anim_channels(ac.data, ac.datatype, 1, ACHANNEL_SETFLAG_ADD);
+               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_SELECT, NULL);
@@ -1448,6 +1682,7 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh
                case ANIMTYPE_DSPART:
                case ANIMTYPE_DSMBALL:
                case ANIMTYPE_DSARM:
+               case ANIMTYPE_DSMESH:
                {
                        /* sanity checking... */
                        if (ale->adt) {
@@ -1458,7 +1693,7 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh
                                }
                                else {
                                        /* select AnimData block by itself */
-                                       ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+                                       ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
                                        ale->adt->flag |= ADT_UI_SELECTED;
                                }
                                
@@ -1485,7 +1720,7 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh
                                FCurve *fcu;
                                
                                /* deselect all other channels */
-                               ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+                               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)
@@ -1494,7 +1729,7 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh
                        }
                        else {
                                /* select group by itself */
-                               ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+                               ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
                                agrp->flag |= AGRP_SELECTED;
                        }
                        
@@ -1516,7 +1751,7 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh
                        }
                        else {
                                /* select F-Curve by itself */
-                               ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+                               ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
                                fcu->flag |= FCURVE_SELECTED;
                        }
                        
@@ -1538,7 +1773,7 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh
                        }
                        else {
                                /* select ShapeKey by itself */
-                               ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+                               ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
                                kb->flag |= KEYBLOCK_SEL;
                        }
                                
@@ -1693,11 +1928,13 @@ void ED_operatortypes_animchannels(void)
        WM_operatortype_append(ANIM_OT_channels_collapse);
        
        WM_operatortype_append(ANIM_OT_channels_visibility_toggle);
+       WM_operatortype_append(ANIM_OT_channels_visibility_set);
 }
 
+// TODO: check on a poll callback for this, to get hotkeys into menus
 void ED_keymap_animchannels(wmKeyConfig *keyconf)
 {
-       wmKeyMap *keymap = WM_keymap_find(keyconf, "Animation_Channels", 0, 0);
+       wmKeyMap *keymap = WM_keymap_find(keyconf, "Animation Channels", 0, 0);
        
        /* selection */
                /* click-select */
@@ -1712,6 +1949,7 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
        
                /* 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);
        
        /* delete */
        WM_keymap_add_item(keymap, "ANIM_OT_channels_delete", XKEY, KM_PRESS, 0, 0);
@@ -1729,8 +1967,8 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
        WM_keymap_add_item(keymap, "ANIM_OT_channels_expand", PADPLUSKEY, KM_PRESS, 0, 0);
        WM_keymap_add_item(keymap, "ANIM_OT_channels_collapse", PADMINUS, KM_PRESS, 0, 0);
        
-       RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_expand", PADPLUSKEY, KM_PRESS, KM_CTRL, 0)->ptr, "all", 1);
-       RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_collapse", PADMINUS, KM_PRESS, KM_CTRL, 0)->ptr, "all", 1);
+       RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_expand", PADPLUSKEY, KM_PRESS, KM_CTRL, 0)->ptr, "all", 0);
+       RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_collapse", PADMINUS, KM_PRESS, KM_CTRL, 0)->ptr, "all", 0);
        
        /* rearranging - actions only */
        //WM_keymap_add_item(keymap, "ANIM_OT_channels_move_up", PAGEUPKEY, KM_PRESS, KM_SHIFT, 0);
@@ -1739,7 +1977,8 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
        //WM_keymap_add_item(keymap, "ANIM_OT_channels_move_to_bottom", PAGEDOWNKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
        
        /* Graph Editor only */
-       WM_keymap_add_item(keymap, "ANIM_OT_channels_visibility_toggle", VKEY, KM_PRESS, 0, 0);
+       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);
 }
 
 /* ************************************************************************** */