diff options
Diffstat (limited to 'source/blender/editors/animation/anim_channels_edit.c')
-rw-r--r-- | source/blender/editors/animation/anim_channels_edit.c | 5042 |
1 files changed, 2543 insertions, 2499 deletions
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 558c5d5bfc1..c2878a64e97 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -21,7 +21,6 @@ * \ingroup edanimation */ - #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -59,7 +58,7 @@ #include "ED_anim_api.h" #include "ED_armature.h" -#include "ED_keyframes_edit.h" // XXX move the select modes out of there! +#include "ED_keyframes_edit.h" // XXX move the select modes out of there! #include "ED_object.h" #include "ED_screen.h" #include "ED_select_utils.h" @@ -74,178 +73,173 @@ /* 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, eAnimCont_Types datatype, eAnimFilter_Flags filter, void *channel_data, eAnim_ChannelType channel_type) -{ - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - - /* try to build list of filtered items */ - ANIM_animdata_filter(ac, &anim_data, filter, data, datatype); - if (BLI_listbase_is_empty(&anim_data)) - return; - - /* only clear the 'active' flag for the channels of the same type */ - for (ale = anim_data.first; ale; ale = ale->next) { - /* skip if types don't match */ - if (channel_type != ale->type) - continue; - - /* flag to set depends on type */ - switch (ale->type) { - case ANIMTYPE_GROUP: - { - bActionGroup *agrp = (bActionGroup *)ale->data; - - ACHANNEL_SET_FLAG(agrp, ACHANNEL_SETFLAG_CLEAR, AGRP_ACTIVE); - break; - } - case ANIMTYPE_FCURVE: - case ANIMTYPE_NLACURVE: - { - FCurve *fcu = (FCurve *)ale->data; - - ACHANNEL_SET_FLAG(fcu, ACHANNEL_SETFLAG_CLEAR, FCURVE_ACTIVE); - break; - } - case ANIMTYPE_NLATRACK: - { - NlaTrack *nlt = (NlaTrack *)ale->data; - - ACHANNEL_SET_FLAG(nlt, ACHANNEL_SETFLAG_CLEAR, NLATRACK_ACTIVE); - break; - } - case ANIMTYPE_FILLACTD: /* Action Expander */ - case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ - case ANIMTYPE_DSLAM: - case ANIMTYPE_DSCAM: - case ANIMTYPE_DSCACHEFILE: - case ANIMTYPE_DSCUR: - case ANIMTYPE_DSSKEY: - case ANIMTYPE_DSWOR: - case ANIMTYPE_DSPART: - case ANIMTYPE_DSMBALL: - case ANIMTYPE_DSARM: - case ANIMTYPE_DSMESH: - case ANIMTYPE_DSTEX: - case ANIMTYPE_DSLAT: - case ANIMTYPE_DSLINESTYLE: - case ANIMTYPE_DSSPK: - case ANIMTYPE_DSGPENCIL: - case ANIMTYPE_DSMCLIP: - { - /* need to verify that this data is valid for now */ - if (ale->adt) { - ACHANNEL_SET_FLAG(ale->adt, ACHANNEL_SETFLAG_CLEAR, ADT_UI_ACTIVE); - } - break; - } - case ANIMTYPE_GPLAYER: - { - bGPDlayer *gpl = (bGPDlayer *)ale->data; - - ACHANNEL_SET_FLAG(gpl, ACHANNEL_SETFLAG_CLEAR, GP_LAYER_ACTIVE); - break; - } - } - } - - /* set active flag */ - if (channel_data) { - switch (channel_type) { - case ANIMTYPE_GROUP: - { - bActionGroup *agrp = (bActionGroup *)channel_data; - agrp->flag |= AGRP_ACTIVE; - break; - } - case ANIMTYPE_FCURVE: - case ANIMTYPE_NLACURVE: - { - FCurve *fcu = (FCurve *)channel_data; - fcu->flag |= FCURVE_ACTIVE; - break; - } - case ANIMTYPE_NLATRACK: - { - NlaTrack *nlt = (NlaTrack *)channel_data; - nlt->flag |= NLATRACK_ACTIVE; - break; - } - case ANIMTYPE_FILLACTD: /* Action Expander */ - case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ - case ANIMTYPE_DSLAM: - case ANIMTYPE_DSCAM: - case ANIMTYPE_DSCACHEFILE: - case ANIMTYPE_DSCUR: - case ANIMTYPE_DSSKEY: - case ANIMTYPE_DSWOR: - case ANIMTYPE_DSPART: - case ANIMTYPE_DSMBALL: - case ANIMTYPE_DSARM: - case ANIMTYPE_DSMESH: - case ANIMTYPE_DSLAT: - case ANIMTYPE_DSLINESTYLE: - case ANIMTYPE_DSSPK: - case ANIMTYPE_DSNTREE: - case ANIMTYPE_DSTEX: - case ANIMTYPE_DSGPENCIL: - case ANIMTYPE_DSMCLIP: - { - /* need to verify that this data is valid for now */ - if (ale && ale->adt) { - ale->adt->flag |= ADT_UI_ACTIVE; - } - break; - } - - case ANIMTYPE_GPLAYER: - { - bGPDlayer *gpl = (bGPDlayer *)channel_data; - gpl->flag |= GP_LAYER_ACTIVE; - break; - } - - /* unhandled currently, but may be interesting */ - case ANIMTYPE_MASKLAYER: - case ANIMTYPE_SHAPEKEY: - case ANIMTYPE_NLAACTION: - break; - - /* other types */ - default: - break; - } - } - - /* clean up */ - ANIM_animdata_freelist(&anim_data); +void ANIM_set_active_channel(bAnimContext *ac, + void *data, + eAnimCont_Types datatype, + eAnimFilter_Flags filter, + void *channel_data, + eAnim_ChannelType channel_type) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + + /* try to build list of filtered items */ + ANIM_animdata_filter(ac, &anim_data, filter, data, datatype); + if (BLI_listbase_is_empty(&anim_data)) + return; + + /* only clear the 'active' flag for the channels of the same type */ + for (ale = anim_data.first; ale; ale = ale->next) { + /* skip if types don't match */ + if (channel_type != ale->type) + continue; + + /* flag to set depends on type */ + switch (ale->type) { + case ANIMTYPE_GROUP: { + bActionGroup *agrp = (bActionGroup *)ale->data; + + ACHANNEL_SET_FLAG(agrp, ACHANNEL_SETFLAG_CLEAR, AGRP_ACTIVE); + break; + } + case ANIMTYPE_FCURVE: + case ANIMTYPE_NLACURVE: { + FCurve *fcu = (FCurve *)ale->data; + + ACHANNEL_SET_FLAG(fcu, ACHANNEL_SETFLAG_CLEAR, FCURVE_ACTIVE); + break; + } + case ANIMTYPE_NLATRACK: { + NlaTrack *nlt = (NlaTrack *)ale->data; + + ACHANNEL_SET_FLAG(nlt, ACHANNEL_SETFLAG_CLEAR, NLATRACK_ACTIVE); + break; + } + case ANIMTYPE_FILLACTD: /* Action Expander */ + case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ + case ANIMTYPE_DSLAM: + case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCACHEFILE: + case ANIMTYPE_DSCUR: + case ANIMTYPE_DSSKEY: + case ANIMTYPE_DSWOR: + case ANIMTYPE_DSPART: + case ANIMTYPE_DSMBALL: + case ANIMTYPE_DSARM: + case ANIMTYPE_DSMESH: + case ANIMTYPE_DSTEX: + case ANIMTYPE_DSLAT: + case ANIMTYPE_DSLINESTYLE: + case ANIMTYPE_DSSPK: + case ANIMTYPE_DSGPENCIL: + case ANIMTYPE_DSMCLIP: { + /* need to verify that this data is valid for now */ + if (ale->adt) { + ACHANNEL_SET_FLAG(ale->adt, ACHANNEL_SETFLAG_CLEAR, ADT_UI_ACTIVE); + } + break; + } + case ANIMTYPE_GPLAYER: { + bGPDlayer *gpl = (bGPDlayer *)ale->data; + + ACHANNEL_SET_FLAG(gpl, ACHANNEL_SETFLAG_CLEAR, GP_LAYER_ACTIVE); + break; + } + } + } + + /* set active flag */ + if (channel_data) { + switch (channel_type) { + case ANIMTYPE_GROUP: { + bActionGroup *agrp = (bActionGroup *)channel_data; + agrp->flag |= AGRP_ACTIVE; + break; + } + case ANIMTYPE_FCURVE: + case ANIMTYPE_NLACURVE: { + FCurve *fcu = (FCurve *)channel_data; + fcu->flag |= FCURVE_ACTIVE; + break; + } + case ANIMTYPE_NLATRACK: { + NlaTrack *nlt = (NlaTrack *)channel_data; + nlt->flag |= NLATRACK_ACTIVE; + break; + } + case ANIMTYPE_FILLACTD: /* Action Expander */ + case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ + case ANIMTYPE_DSLAM: + case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCACHEFILE: + case ANIMTYPE_DSCUR: + case ANIMTYPE_DSSKEY: + case ANIMTYPE_DSWOR: + case ANIMTYPE_DSPART: + case ANIMTYPE_DSMBALL: + case ANIMTYPE_DSARM: + case ANIMTYPE_DSMESH: + case ANIMTYPE_DSLAT: + case ANIMTYPE_DSLINESTYLE: + case ANIMTYPE_DSSPK: + case ANIMTYPE_DSNTREE: + case ANIMTYPE_DSTEX: + case ANIMTYPE_DSGPENCIL: + case ANIMTYPE_DSMCLIP: { + /* need to verify that this data is valid for now */ + if (ale && ale->adt) { + ale->adt->flag |= ADT_UI_ACTIVE; + } + break; + } + + case ANIMTYPE_GPLAYER: { + bGPDlayer *gpl = (bGPDlayer *)channel_data; + gpl->flag |= GP_LAYER_ACTIVE; + break; + } + + /* unhandled currently, but may be interesting */ + case ANIMTYPE_MASKLAYER: + case ANIMTYPE_SHAPEKEY: + case ANIMTYPE_NLAACTION: + break; + + /* other types */ + default: + break; + } + } + + /* clean up */ + ANIM_animdata_freelist(&anim_data); } static void select_pchan_for_action_group(bAnimContext *ac, bActionGroup *agrp, bAnimListElem *ale) { - /* Armatures-Specific Feature: - * See mouse_anim_channels() -> ANIMTYPE_GROUP case for more details (T38737) - */ - if ((ac->ads->filterflag & ADS_FILTER_ONLYSEL) == 0) { - if ((ale->id) && (GS(ale->id->name) == ID_OB)) { - Object *ob = (Object *)ale->id; - if (ob->type == OB_ARMATURE) { - /* Assume for now that any group with corresponding name is what we want - * (i.e. for an armature whose location is animated, things would break - * if the user were to add a bone named "Location"). - * - * TODO: check the first F-Curve or so to be sure... - */ - bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, agrp->name); - if (agrp->flag & AGRP_SELECTED) { - ED_pose_bone_select(ob, pchan, true); - } - else { - ED_pose_bone_select(ob, pchan, false); - } - } - } - } + /* Armatures-Specific Feature: + * See mouse_anim_channels() -> ANIMTYPE_GROUP case for more details (T38737) + */ + if ((ac->ads->filterflag & ADS_FILTER_ONLYSEL) == 0) { + if ((ale->id) && (GS(ale->id->name) == ID_OB)) { + Object *ob = (Object *)ale->id; + if (ob->type == OB_ARMATURE) { + /* Assume for now that any group with corresponding name is what we want + * (i.e. for an armature whose location is animated, things would break + * if the user were to add a bone named "Location"). + * + * TODO: check the first F-Curve or so to be sure... + */ + bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, agrp->name); + if (agrp->flag & AGRP_SELECTED) { + ED_pose_bone_select(ob, pchan, true); + } + else { + ED_pose_bone_select(ob, pchan, false); + } + } + } + } } /* Deselect all animation channels @@ -254,195 +248,186 @@ static void select_pchan_for_action_group(bAnimContext *ac, bActionGroup *agrp, * - test: check if deselecting instead of selecting * - sel: eAnimChannels_SetFlag; */ -void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types datatype, bool test, eAnimChannels_SetFlag sel) -{ - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - /* filter data */ - /* NOTE: no list visible, otherwise, we get dangling */ - 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) { - if (sel == 0) - break; - - switch (ale->type) { - case ANIMTYPE_SCENE: - if (ale->flag & SCE_DS_SELECTED) - 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 (ale->flag & SELECT) - sel = ACHANNEL_SETFLAG_CLEAR; +void ANIM_deselect_anim_channels( + bAnimContext *ac, void *data, eAnimCont_Types datatype, bool test, eAnimChannels_SetFlag sel) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* filter data */ + /* NOTE: no list visible, otherwise, we get dangling */ + 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) { + if (sel == 0) + break; + + switch (ale->type) { + case ANIMTYPE_SCENE: + if (ale->flag & SCE_DS_SELECTED) + 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 (ale->flag & SELECT) + sel = ACHANNEL_SETFLAG_CLEAR; #endif - break; - case ANIMTYPE_GROUP: - if (ale->flag & AGRP_SELECTED) - sel = ACHANNEL_SETFLAG_CLEAR; - break; - case ANIMTYPE_FCURVE: - case ANIMTYPE_NLACURVE: - if (ale->flag & FCURVE_SELECTED) - sel = ACHANNEL_SETFLAG_CLEAR; - break; - case ANIMTYPE_SHAPEKEY: - if (ale->flag & KEYBLOCK_SEL) - sel = ACHANNEL_SETFLAG_CLEAR; - break; - case ANIMTYPE_NLATRACK: - if (ale->flag & NLATRACK_SELECTED) - sel = ACHANNEL_SETFLAG_CLEAR; - break; - - case ANIMTYPE_FILLACTD: /* Action Expander */ - case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ - case ANIMTYPE_DSLAM: - case ANIMTYPE_DSCAM: - case ANIMTYPE_DSCACHEFILE: - case ANIMTYPE_DSCUR: - case ANIMTYPE_DSSKEY: - case ANIMTYPE_DSWOR: - case ANIMTYPE_DSPART: - case ANIMTYPE_DSMBALL: - case ANIMTYPE_DSARM: - case ANIMTYPE_DSMESH: - case ANIMTYPE_DSNTREE: - case ANIMTYPE_DSTEX: - case ANIMTYPE_DSLAT: - case ANIMTYPE_DSLINESTYLE: - case ANIMTYPE_DSSPK: - case ANIMTYPE_DSGPENCIL: - case ANIMTYPE_DSMCLIP: - { - if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED)) - sel = ACHANNEL_SETFLAG_CLEAR; - break; - } - case ANIMTYPE_GPLAYER: - if (ale->flag & GP_LAYER_SELECT) - 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) { - switch (ale->type) { - case ANIMTYPE_SCENE: - { - Scene *scene = (Scene *)ale->data; - - ACHANNEL_SET_FLAG(scene, sel, SCE_DS_SELECTED); - - if (scene->adt) { - ACHANNEL_SET_FLAG(scene, sel, ADT_UI_SELECTED); - } - 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); - } + break; + case ANIMTYPE_GROUP: + if (ale->flag & AGRP_SELECTED) + sel = ACHANNEL_SETFLAG_CLEAR; + break; + case ANIMTYPE_FCURVE: + case ANIMTYPE_NLACURVE: + if (ale->flag & FCURVE_SELECTED) + sel = ACHANNEL_SETFLAG_CLEAR; + break; + case ANIMTYPE_SHAPEKEY: + if (ale->flag & KEYBLOCK_SEL) + sel = ACHANNEL_SETFLAG_CLEAR; + break; + case ANIMTYPE_NLATRACK: + if (ale->flag & NLATRACK_SELECTED) + sel = ACHANNEL_SETFLAG_CLEAR; + break; + + case ANIMTYPE_FILLACTD: /* Action Expander */ + case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ + case ANIMTYPE_DSLAM: + case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCACHEFILE: + case ANIMTYPE_DSCUR: + case ANIMTYPE_DSSKEY: + case ANIMTYPE_DSWOR: + case ANIMTYPE_DSPART: + case ANIMTYPE_DSMBALL: + case ANIMTYPE_DSARM: + case ANIMTYPE_DSMESH: + case ANIMTYPE_DSNTREE: + case ANIMTYPE_DSTEX: + case ANIMTYPE_DSLAT: + case ANIMTYPE_DSLINESTYLE: + case ANIMTYPE_DSSPK: + case ANIMTYPE_DSGPENCIL: + case ANIMTYPE_DSMCLIP: { + if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED)) + sel = ACHANNEL_SETFLAG_CLEAR; + break; + } + case ANIMTYPE_GPLAYER: + if (ale->flag & GP_LAYER_SELECT) + 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) { + switch (ale->type) { + case ANIMTYPE_SCENE: { + Scene *scene = (Scene *)ale->data; + + ACHANNEL_SET_FLAG(scene, sel, SCE_DS_SELECTED); + + if (scene->adt) { + ACHANNEL_SET_FLAG(scene, sel, ADT_UI_SELECTED); + } + 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); + } #endif - break; - } - case ANIMTYPE_GROUP: - { - bActionGroup *agrp = (bActionGroup *)ale->data; - ACHANNEL_SET_FLAG(agrp, sel, AGRP_SELECTED); - select_pchan_for_action_group(ac, agrp, ale); - agrp->flag &= ~AGRP_ACTIVE; - break; - } - case ANIMTYPE_FCURVE: - case ANIMTYPE_NLACURVE: - { - FCurve *fcu = (FCurve *)ale->data; - - ACHANNEL_SET_FLAG(fcu, sel, FCURVE_SELECTED); - fcu->flag &= ~FCURVE_ACTIVE; - break; - } - case ANIMTYPE_SHAPEKEY: - { - KeyBlock *kb = (KeyBlock *)ale->data; - - ACHANNEL_SET_FLAG(kb, sel, KEYBLOCK_SEL); - break; - } - case ANIMTYPE_NLATRACK: - { - NlaTrack *nlt = (NlaTrack *)ale->data; - - ACHANNEL_SET_FLAG(nlt, sel, NLATRACK_SELECTED); - nlt->flag &= ~NLATRACK_ACTIVE; - break; - } - case ANIMTYPE_FILLACTD: /* Action Expander */ - case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ - case ANIMTYPE_DSLAM: - case ANIMTYPE_DSCAM: - case ANIMTYPE_DSCACHEFILE: - case ANIMTYPE_DSCUR: - case ANIMTYPE_DSSKEY: - case ANIMTYPE_DSWOR: - case ANIMTYPE_DSPART: - case ANIMTYPE_DSMBALL: - case ANIMTYPE_DSARM: - case ANIMTYPE_DSMESH: - case ANIMTYPE_DSNTREE: - case ANIMTYPE_DSTEX: - case ANIMTYPE_DSLAT: - case ANIMTYPE_DSLINESTYLE: - case ANIMTYPE_DSSPK: - case ANIMTYPE_DSGPENCIL: - case ANIMTYPE_DSMCLIP: - { - /* need to verify that this data is valid for now */ - if (ale->adt) { - ACHANNEL_SET_FLAG(ale->adt, sel, ADT_UI_SELECTED); - ale->adt->flag &= ~ADT_UI_ACTIVE; - } - break; - } - case ANIMTYPE_GPLAYER: - { - bGPDlayer *gpl = (bGPDlayer *)ale->data; - - ACHANNEL_SET_FLAG(gpl, sel, GP_LAYER_SELECT); - break; - } - case ANIMTYPE_MASKLAYER: - { - MaskLayer *masklay = (MaskLayer *)ale->data; - - ACHANNEL_SET_FLAG(masklay, sel, MASK_LAYERFLAG_SELECT); - break; - } - } - } - - /* Cleanup */ - ANIM_animdata_freelist(&anim_data); + break; + } + case ANIMTYPE_GROUP: { + bActionGroup *agrp = (bActionGroup *)ale->data; + ACHANNEL_SET_FLAG(agrp, sel, AGRP_SELECTED); + select_pchan_for_action_group(ac, agrp, ale); + agrp->flag &= ~AGRP_ACTIVE; + break; + } + case ANIMTYPE_FCURVE: + case ANIMTYPE_NLACURVE: { + FCurve *fcu = (FCurve *)ale->data; + + ACHANNEL_SET_FLAG(fcu, sel, FCURVE_SELECTED); + fcu->flag &= ~FCURVE_ACTIVE; + break; + } + case ANIMTYPE_SHAPEKEY: { + KeyBlock *kb = (KeyBlock *)ale->data; + + ACHANNEL_SET_FLAG(kb, sel, KEYBLOCK_SEL); + break; + } + case ANIMTYPE_NLATRACK: { + NlaTrack *nlt = (NlaTrack *)ale->data; + + ACHANNEL_SET_FLAG(nlt, sel, NLATRACK_SELECTED); + nlt->flag &= ~NLATRACK_ACTIVE; + break; + } + case ANIMTYPE_FILLACTD: /* Action Expander */ + case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ + case ANIMTYPE_DSLAM: + case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCACHEFILE: + case ANIMTYPE_DSCUR: + case ANIMTYPE_DSSKEY: + case ANIMTYPE_DSWOR: + case ANIMTYPE_DSPART: + case ANIMTYPE_DSMBALL: + case ANIMTYPE_DSARM: + case ANIMTYPE_DSMESH: + case ANIMTYPE_DSNTREE: + case ANIMTYPE_DSTEX: + case ANIMTYPE_DSLAT: + case ANIMTYPE_DSLINESTYLE: + case ANIMTYPE_DSSPK: + case ANIMTYPE_DSGPENCIL: + case ANIMTYPE_DSMCLIP: { + /* need to verify that this data is valid for now */ + if (ale->adt) { + ACHANNEL_SET_FLAG(ale->adt, sel, ADT_UI_SELECTED); + ale->adt->flag &= ~ADT_UI_ACTIVE; + } + break; + } + case ANIMTYPE_GPLAYER: { + bGPDlayer *gpl = (bGPDlayer *)ale->data; + + ACHANNEL_SET_FLAG(gpl, sel, GP_LAYER_SELECT); + break; + } + case ANIMTYPE_MASKLAYER: { + MaskLayer *masklay = (MaskLayer *)ale->data; + + ACHANNEL_SET_FLAG(masklay, sel, MASK_LAYERFLAG_SELECT); + break; + } + } + } + + /* Cleanup */ + ANIM_animdata_freelist(&anim_data); } /* ---------------------------- Graph Editor ------------------------------------- */ @@ -456,137 +441,140 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d * - 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, eAnimChannel_Settings setting, eAnimChannels_SetFlag mode) -{ - bAnimListElem *ale, *match = NULL; - int prevLevel = 0, matchLevel = 0; - - /* sanity check */ - if (ELEM(NULL, anim_data, anim_data->first)) - return; - - if (setting == ACHANNEL_SETTING_ALWAYS_VISIBLE) { - 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 { - const 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) && (mode != ACHANNEL_SETFLAG_CLEAR)) || - ((setting != ACHANNEL_SETTING_VISIBLE) && (mode == ACHANNEL_SETFLAG_CLEAR))) - { - /* go backwards in the list, until the highest-ranking element (by indention has been covered) */ - for (ale = match->prev; ale; ale = ale->prev) { - const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); - int level; - - /* if no channel info was found, skip, since this type might not have any useful info */ - 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, which should happen if we don't let prevLevel - * get updated below once the first 1st group is found)... - */ - if (level < prevLevel) { - /* flush the new status... */ - ANIM_channel_setting_set(ac, ale, setting, mode); - - /* store this level as the 'old' level now */ - 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), - * stop here - */ - if (prevLevel == 0) - break; - /* otherwise, this level weaves into another sibling hierarchy to the previous one just - * finished, so skip until we get to the parent of this level - */ - else - continue; - } - } - } - - /* 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) { - const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); - int level; - - /* if no channel info was found, skip, since this type might not have any useful info */ - 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, mode); - /* however, if the level is 'less than or equal to' the channel that was changed, - * (i.e. the current channel is as important if not more important than the changed channel) - * then we should stop, since we've found the last one of the children we should flush - */ - else - break; - - /* store this level as the 'old' level now */ - // prevLevel = level; // XXX: prevLevel is unused - } - } +void ANIM_flush_setting_anim_channels(bAnimContext *ac, + ListBase *anim_data, + bAnimListElem *ale_setting, + eAnimChannel_Settings setting, + eAnimChannels_SetFlag mode) +{ + bAnimListElem *ale, *match = NULL; + int prevLevel = 0, matchLevel = 0; + + /* sanity check */ + if (ELEM(NULL, anim_data, anim_data->first)) + return; + + if (setting == ACHANNEL_SETTING_ALWAYS_VISIBLE) { + 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 { + const 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) && (mode != ACHANNEL_SETFLAG_CLEAR)) || + ((setting != ACHANNEL_SETTING_VISIBLE) && (mode == ACHANNEL_SETFLAG_CLEAR))) { + /* go backwards in the list, until the highest-ranking element (by indention has been covered) */ + for (ale = match->prev; ale; ale = ale->prev) { + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + int level; + + /* if no channel info was found, skip, since this type might not have any useful info */ + 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, which should happen if we don't let prevLevel + * get updated below once the first 1st group is found)... + */ + if (level < prevLevel) { + /* flush the new status... */ + ANIM_channel_setting_set(ac, ale, setting, mode); + + /* store this level as the 'old' level now */ + 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), + * stop here + */ + if (prevLevel == 0) + break; + /* otherwise, this level weaves into another sibling hierarchy to the previous one just + * finished, so skip until we get to the parent of this level + */ + else + continue; + } + } + } + + /* 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) { + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + int level; + + /* if no channel info was found, skip, since this type might not have any useful info */ + 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, mode); + /* however, if the level is 'less than or equal to' the channel that was changed, + * (i.e. the current channel is as important if not more important than the changed channel) + * then we should stop, since we've found the last one of the children we should flush + */ + else + break; + + /* store this level as the 'old' level now */ + // prevLevel = level; // XXX: prevLevel is unused + } + } } /* -------------------------- F-Curves ------------------------------------- */ @@ -594,59 +582,59 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn /* 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 ((ac) && (ac->datatype == ANIMCONT_DRIVERS)) { - /* driver F-Curve */ - 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) { - 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 (BLI_listbase_is_empty(&agrp->channels)) { - 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. - * - * This is done so that we don't have dangling Object+Action entries in - * channel list that are empty, and linger around long after the data they - * are for has disappeared (and probably won't come back). - */ - if (BLI_listbase_is_empty(&act->curves) && (adt->flag & ADT_NLA_EDIT_ON) == 0) { - id_us_min(&act->id); - adt->action = NULL; - } - } - - /* free the F-Curve itself */ - free_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 ((ac) && (ac->datatype == ANIMCONT_DRIVERS)) { + /* driver F-Curve */ + 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) { + 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 (BLI_listbase_is_empty(&agrp->channels)) { + 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. + * + * This is done so that we don't have dangling Object+Action entries in + * channel list that are empty, and linger around long after the data they + * are for has disappeared (and probably won't come back). + */ + if (BLI_listbase_is_empty(&act->curves) && (adt->flag & ADT_NLA_EDIT_ON) == 0) { + id_us_min(&act->id); + adt->action = NULL; + } + } + + /* free the F-Curve itself */ + free_fcurve(fcu); } /* ************************************************************************** */ @@ -657,40 +645,40 @@ void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, AnimData *adt, FCurve *f /* poll callback for being in an Animation Editor channels list region */ static bool 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? */ - if (ELEM(NULL, sa, CTX_wm_region(C))) - return 0; - /* animation editor test */ - if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA) == 0) - return 0; + /* 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 */ + if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA) == 0) + return 0; - return 1; + return 1; } /* poll callback for Animation Editor channels list region + not in NLA-tweakmode for NLA */ static bool animedit_poll_channels_nla_tweakmode_off(bContext *C) { - ScrArea *sa = CTX_wm_area(C); - Scene *scene = CTX_data_scene(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? */ - if (ELEM(NULL, sa, CTX_wm_region(C))) - return 0; - /* animation editor test */ - if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA) == 0) - return 0; + /* 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 */ + if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA) == 0) + return 0; - /* NLA TweakMode test */ - if (sa->spacetype == SPACE_NLA) { - if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON)) - return 0; - } + /* NLA TweakMode test */ + if (sa->spacetype == SPACE_NLA) { + if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON)) + return 0; + } - return 1; + return 1; } /* ****************** Rearrange Channels Operator ******************* */ @@ -698,146 +686,144 @@ static bool animedit_poll_channels_nla_tweakmode_off(bContext *C) /* constants for channel rearranging */ /* WARNING: don't change existing ones without modifying rearrange func accordingly */ typedef enum eRearrangeAnimChan_Mode { - REARRANGE_ANIMCHAN_TOP = -2, - REARRANGE_ANIMCHAN_UP = -1, - REARRANGE_ANIMCHAN_DOWN = 1, - REARRANGE_ANIMCHAN_BOTTOM = 2, + REARRANGE_ANIMCHAN_TOP = -2, + REARRANGE_ANIMCHAN_UP = -1, + REARRANGE_ANIMCHAN_DOWN = 1, + REARRANGE_ANIMCHAN_BOTTOM = 2, } eRearrangeAnimChan_Mode; /* defines for rearranging channels */ static const EnumPropertyItem prop_animchannel_rearrange_types[] = { - {REARRANGE_ANIMCHAN_TOP, "TOP", 0, "To Top", ""}, - {REARRANGE_ANIMCHAN_UP, "UP", 0, "Up", ""}, - {REARRANGE_ANIMCHAN_DOWN, "DOWN", 0, "Down", ""}, - {REARRANGE_ANIMCHAN_BOTTOM, "BOTTOM", 0, "To Bottom", ""}, - {0, NULL, 0, NULL, NULL}, + {REARRANGE_ANIMCHAN_TOP, "TOP", 0, "To Top", ""}, + {REARRANGE_ANIMCHAN_UP, "UP", 0, "Up", ""}, + {REARRANGE_ANIMCHAN_DOWN, "DOWN", 0, "Down", ""}, + {REARRANGE_ANIMCHAN_BOTTOM, "BOTTOM", 0, "To Bottom", ""}, + {0, NULL, 0, NULL, NULL}, }; /* Reordering "Islands" Defines ----------------------------------- */ /* Island definition - just a listbase container */ typedef struct tReorderChannelIsland { - struct tReorderChannelIsland *next, *prev; + 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_HIDDEN = (1 << 3), /* island is not visible */ + 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_HIDDEN = (1 << 3), /* island is not visible */ } eReorderIslandFlag; - /* Rearrange Methods --------------------------------------------- */ static bool rearrange_island_ok(tReorderChannelIsland *island) { - /* island must not be untouchable */ - if (island->flag & REORDER_ISLAND_UNTOUCHABLE) - return 0; + /* island must not be untouchable */ + if (island->flag & REORDER_ISLAND_UNTOUCHABLE) + return 0; - /* island should be selected to be moved */ - return (island->flag & REORDER_ISLAND_SELECTED) && !(island->flag & REORDER_ISLAND_MOVED); + /* island should be selected to be moved */ + return (island->flag & REORDER_ISLAND_SELECTED) && !(island->flag & REORDER_ISLAND_MOVED); } /* ............................. */ static bool rearrange_island_top(ListBase *list, tReorderChannelIsland *island) { - if (rearrange_island_ok(island)) { - /* remove from current position */ - BLI_remlink(list, island); + if (rearrange_island_ok(island)) { + /* remove from current position */ + BLI_remlink(list, island); - /* make it first element */ - BLI_insertlinkbefore(list, list->first, island); + /* make it first element */ + BLI_insertlinkbefore(list, list->first, island); - return 1; - } + return 1; + } - return 0; + return 0; } static bool rearrange_island_up(ListBase *list, tReorderChannelIsland *island) { - if (rearrange_island_ok(island)) { - /* moving up = moving before the previous island, otherwise we're in the same place */ - tReorderChannelIsland *prev = island->prev; + if (rearrange_island_ok(island)) { + /* moving up = moving before the previous island, otherwise we're in the same place */ + tReorderChannelIsland *prev = island->prev; - /* Skip hidden islands! */ - while (prev && prev->flag & REORDER_ISLAND_HIDDEN) { - prev = prev->prev; - } + /* Skip hidden islands! */ + while (prev && prev->flag & REORDER_ISLAND_HIDDEN) { + prev = prev->prev; + } - if (prev) { - /* remove from current position */ - BLI_remlink(list, island); + if (prev) { + /* remove from current position */ + BLI_remlink(list, island); - /* push it up */ - BLI_insertlinkbefore(list, prev, island); + /* push it up */ + BLI_insertlinkbefore(list, prev, island); - return 1; - } - } + return 1; + } + } - return 0; + return 0; } static bool rearrange_island_down(ListBase *list, tReorderChannelIsland *island) { - if (rearrange_island_ok(island)) { - /* moving down = moving after the next island, otherwise we're in the same place */ - tReorderChannelIsland *next = island->next; + if (rearrange_island_ok(island)) { + /* moving down = moving after the next island, otherwise we're in the same place */ + tReorderChannelIsland *next = island->next; - /* Skip hidden islands! */ - while (next && next->flag & REORDER_ISLAND_HIDDEN) { - next = next->next; - } + /* Skip hidden islands! */ + while (next && next->flag & REORDER_ISLAND_HIDDEN) { + next = next->next; + } - if (next) { - /* can only move past if next is not untouchable (i.e. nothing can go after it) */ - if ((next->flag & REORDER_ISLAND_UNTOUCHABLE) == 0) { - /* remove from current position */ - BLI_remlink(list, island); + 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) { + /* remove from current position */ + BLI_remlink(list, island); - /* push it down */ - BLI_insertlinkafter(list, next, island); + /* push it down */ + BLI_insertlinkafter(list, next, island); - return true; - } - } - /* else: no next channel, so we're at the bottom already, so can't move */ - } + return true; + } + } + /* else: no next channel, so we're at the bottom already, so can't move */ + } - return false; + return false; } static bool rearrange_island_bottom(ListBase *list, tReorderChannelIsland *island) { - if (rearrange_island_ok(island)) { - tReorderChannelIsland *last = list->last; - - /* remove island from current position */ - BLI_remlink(list, island); + if (rearrange_island_ok(island)) { + tReorderChannelIsland *last = list->last; - /* add before or after the last channel? */ - if ((last->flag & REORDER_ISLAND_UNTOUCHABLE) == 0) { - /* can add after it */ - BLI_addtail(list, island); - } - else { - /* can at most go just before it, since last cannot be moved */ - BLI_insertlinkbefore(list, last, island); + /* remove island from current position */ + BLI_remlink(list, island); - } + /* add before or after the last channel? */ + if ((last->flag & REORDER_ISLAND_UNTOUCHABLE) == 0) { + /* can add after it */ + BLI_addtail(list, island); + } + else { + /* can at most go just before it, since last cannot be moved */ + BLI_insertlinkbefore(list, last, island); + } - return true; - } + return true; + } - return false; + return false; } /* ............................. */ @@ -854,184 +840,187 @@ typedef bool (*AnimChanRearrangeFp)(ListBase *list, tReorderChannelIsland *islan /* get rearranging function, given 'rearrange' mode */ static AnimChanRearrangeFp rearrange_get_mode_func(eRearrangeAnimChan_Mode mode) { - switch (mode) { - case REARRANGE_ANIMCHAN_TOP: - return rearrange_island_top; - case REARRANGE_ANIMCHAN_UP: - return rearrange_island_up; - case REARRANGE_ANIMCHAN_DOWN: - return rearrange_island_down; - case REARRANGE_ANIMCHAN_BOTTOM: - return rearrange_island_bottom; - default: - return NULL; - } + switch (mode) { + case REARRANGE_ANIMCHAN_TOP: + return rearrange_island_top; + case REARRANGE_ANIMCHAN_UP: + return rearrange_island_up; + case REARRANGE_ANIMCHAN_DOWN: + return rearrange_island_down; + case REARRANGE_ANIMCHAN_BOTTOM: + return rearrange_island_bottom; + default: + return NULL; + } } /* Rearrange Islands Generics ------------------------------------- */ /* add channel into list of islands */ -static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *srcList, - Link *channel, eAnim_ChannelType type, +static void rearrange_animchannel_add_to_islands(ListBase *islands, + ListBase *srcList, + Link *channel, + eAnim_ChannelType type, const bool is_hidden) { - /* always try to add to last island if possible */ - tReorderChannelIsland *island = islands->last; - bool is_sel = false, is_untouchable = false; - - /* get flags - selected and untouchable from the channel */ - switch (type) { - case ANIMTYPE_GROUP: - { - bActionGroup *agrp = (bActionGroup *)channel; - - is_sel = SEL_AGRP(agrp); - is_untouchable = (agrp->flag & AGRP_TEMP) != 0; - break; - } - case ANIMTYPE_FCURVE: - case ANIMTYPE_NLACURVE: - { - FCurve *fcu = (FCurve *)channel; - - is_sel = SEL_FCU(fcu); - break; - } - case ANIMTYPE_NLATRACK: - { - NlaTrack *nlt = (NlaTrack *)channel; - - is_sel = SEL_NLT(nlt); - break; - } - case ANIMTYPE_GPLAYER: - { - bGPDlayer *gpl = (bGPDlayer *)channel; - - is_sel = SEL_GPL(gpl); - break; - } - default: - printf("rearrange_animchannel_add_to_islands(): don't know how to handle channels of type %u\n", type); - return; - } - - /* do we need to add to a new island? */ - if (/* 1) no islands yet */ - (island == NULL) || - /* 2) unselected islands have single channels only - to allow up/down movement */ - ((island->flag & REORDER_ISLAND_SELECTED) == 0) || - /* 3) if channel is unselected, stop existing island (it was either wrong sel status, or full already) */ - (is_sel == 0) || - /* 4) hidden status changes */ - ((island->flag & REORDER_ISLAND_HIDDEN) != is_hidden) - ) - { - /* create a new island now */ - island = MEM_callocN(sizeof(tReorderChannelIsland), "tReorderChannelIsland"); - BLI_addtail(islands, island); - - if (is_sel) - island->flag |= REORDER_ISLAND_SELECTED; - if (is_untouchable) - island->flag |= REORDER_ISLAND_UNTOUCHABLE; - if (is_hidden) - island->flag |= REORDER_ISLAND_HIDDEN; - } - - /* add channel to island - need to remove it from its existing list first though */ - BLI_remlink(srcList, channel); - BLI_addtail(&island->channels, channel); + /* always try to add to last island if possible */ + tReorderChannelIsland *island = islands->last; + bool is_sel = false, is_untouchable = false; + + /* get flags - selected and untouchable from the channel */ + switch (type) { + case ANIMTYPE_GROUP: { + bActionGroup *agrp = (bActionGroup *)channel; + + is_sel = SEL_AGRP(agrp); + is_untouchable = (agrp->flag & AGRP_TEMP) != 0; + break; + } + case ANIMTYPE_FCURVE: + case ANIMTYPE_NLACURVE: { + FCurve *fcu = (FCurve *)channel; + + is_sel = SEL_FCU(fcu); + break; + } + case ANIMTYPE_NLATRACK: { + NlaTrack *nlt = (NlaTrack *)channel; + + is_sel = SEL_NLT(nlt); + break; + } + case ANIMTYPE_GPLAYER: { + bGPDlayer *gpl = (bGPDlayer *)channel; + + is_sel = SEL_GPL(gpl); + break; + } + default: + printf( + "rearrange_animchannel_add_to_islands(): don't know how to handle channels of type %u\n", + type); + return; + } + + /* do we need to add to a new island? */ + if (/* 1) no islands yet */ + (island == NULL) || + /* 2) unselected islands have single channels only - to allow up/down movement */ + ((island->flag & REORDER_ISLAND_SELECTED) == 0) || + /* 3) if channel is unselected, stop existing island (it was either wrong sel status, or full already) */ + (is_sel == 0) || + /* 4) hidden status changes */ + ((island->flag & REORDER_ISLAND_HIDDEN) != is_hidden)) { + /* create a new island now */ + island = MEM_callocN(sizeof(tReorderChannelIsland), "tReorderChannelIsland"); + BLI_addtail(islands, island); + + if (is_sel) + island->flag |= REORDER_ISLAND_SELECTED; + if (is_untouchable) + island->flag |= REORDER_ISLAND_UNTOUCHABLE; + if (is_hidden) + island->flag |= REORDER_ISLAND_HIDDEN; + } + + /* add channel to island - need to remove it from its existing list first though */ + BLI_remlink(srcList, channel); + BLI_addtail(&island->channels, channel); } /* flatten islands out into a single list again */ 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(BLI_listbase_is_empty(srcList)); + /* make sure srcList is empty now */ + BLI_assert(BLI_listbase_is_empty(srcList)); - /* go through merging islands */ - for (island = islands->first; island; island = isn) { - isn = island->next; + /* go through merging islands */ + for (island = islands->first; island; island = isn) { + isn = island->next; - /* merge island channels back to main list, then delete the island */ - BLI_movelisttolist(srcList, &island->channels); - BLI_freelinkN(islands, island); - } + /* merge island channels back to main list, then delete the island */ + BLI_movelisttolist(srcList, &island->channels); + BLI_freelinkN(islands, island); + } } /* ............................. */ /* get a list of all bAnimListElem's of a certain type which are currently visible */ -static void rearrange_animchannels_filter_visible(ListBase *anim_data_visible, bAnimContext *ac, eAnim_ChannelType type) +static void rearrange_animchannels_filter_visible(ListBase *anim_data_visible, + bAnimContext *ac, + eAnim_ChannelType type) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale, *ale_next; - int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale, *ale_next; + int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); - /* get all visible channels */ - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + /* get all visible channels */ + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - /* now, only keep the ones that are of the types we are interested in */ - for (ale = anim_data.first; ale; ale = ale_next) { - ale_next = ale->next; + /* now, only keep the ones that are of the types we are interested in */ + for (ale = anim_data.first; ale; ale = ale_next) { + ale_next = ale->next; - if (ale->type != type) { - BLI_freelinkN(&anim_data, ale); - } - } + if (ale->type != type) { + BLI_freelinkN(&anim_data, ale); + } + } - /* return cleaned up list */ - *anim_data_visible = anim_data; + /* return cleaned up list */ + *anim_data_visible = anim_data; } /* performing rearranging of channels using islands */ -static bool rearrange_animchannel_islands(ListBase *list, AnimChanRearrangeFp rearrange_func, - eRearrangeAnimChan_Mode mode, eAnim_ChannelType type, +static bool rearrange_animchannel_islands(ListBase *list, + AnimChanRearrangeFp rearrange_func, + eRearrangeAnimChan_Mode mode, + eAnim_ChannelType type, ListBase *anim_data_visible) { - ListBase islands = {NULL, NULL}; - Link *channel, *chanNext = NULL; - bool done = false; - - /* don't waste effort on an empty list */ - if (BLI_listbase_is_empty(list)) - return 0; - - /* group channels into islands */ - for (channel = list->first; channel; channel = chanNext) { - /* find out whether this channel is present in anim_data_visible or not! */ - const bool is_hidden = (BLI_findptr(anim_data_visible, channel, offsetof(bAnimListElem, data)) == NULL); - chanNext = channel->next; - rearrange_animchannel_add_to_islands(&islands, list, channel, type, is_hidden); - } - - /* perform moving of selected islands now, but only if there is more than one of 'em so that something will happen - * - scanning of the list is performed in the opposite direction to the direction we're moving things, so that we - * shouldn't need to encounter items we've moved already - */ - if (islands.first != islands.last) { - tReorderChannelIsland *first = (mode > 0) ? islands.last : islands.first; - tReorderChannelIsland *island, *isn = NULL; - - for (island = first; island; island = isn) { - isn = (mode > 0) ? island->prev : island->next; - - /* perform rearranging */ - if (rearrange_func(&islands, island)) { - island->flag |= REORDER_ISLAND_MOVED; - done = true; - } - } - } - - /* ungroup islands */ - rearrange_animchannel_flatten_islands(&islands, list); - - /* did we do anything? */ - return done; + ListBase islands = {NULL, NULL}; + Link *channel, *chanNext = NULL; + bool done = false; + + /* don't waste effort on an empty list */ + if (BLI_listbase_is_empty(list)) + return 0; + + /* group channels into islands */ + for (channel = list->first; channel; channel = chanNext) { + /* find out whether this channel is present in anim_data_visible or not! */ + const bool is_hidden = + (BLI_findptr(anim_data_visible, channel, offsetof(bAnimListElem, data)) == NULL); + chanNext = channel->next; + rearrange_animchannel_add_to_islands(&islands, list, channel, type, is_hidden); + } + + /* perform moving of selected islands now, but only if there is more than one of 'em so that something will happen + * - scanning of the list is performed in the opposite direction to the direction we're moving things, so that we + * shouldn't need to encounter items we've moved already + */ + if (islands.first != islands.last) { + tReorderChannelIsland *first = (mode > 0) ? islands.last : islands.first; + tReorderChannelIsland *island, *isn = NULL; + + for (island = first; island; island = isn) { + isn = (mode > 0) ? island->prev : island->next; + + /* perform rearranging */ + if (rearrange_func(&islands, island)) { + island->flag |= REORDER_ISLAND_MOVED; + done = true; + } + } + } + + /* ungroup islands */ + rearrange_animchannel_flatten_islands(&islands, list); + + /* did we do anything? */ + return done; } /* NLA Specific Stuff ----------------------------------------------------- */ @@ -1042,25 +1031,26 @@ static bool rearrange_animchannel_islands(ListBase *list, AnimChanRearrangeFp re */ static void rearrange_nla_channels(bAnimContext *ac, AnimData *adt, eRearrangeAnimChan_Mode mode) { - AnimChanRearrangeFp rearrange_func; - ListBase anim_data_visible = {NULL, NULL}; + AnimChanRearrangeFp rearrange_func; + ListBase anim_data_visible = {NULL, NULL}; - /* hack: invert mode so that functions will work in right order */ - mode *= -1; + /* hack: invert mode so that functions will work in right order */ + mode *= -1; - /* get rearranging function */ - rearrange_func = rearrange_get_mode_func(mode); - if (rearrange_func == NULL) - return; + /* get rearranging function */ + rearrange_func = rearrange_get_mode_func(mode); + if (rearrange_func == NULL) + return; - /* Filter visible data. */ - rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_NLATRACK); + /* Filter visible data. */ + rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_NLATRACK); - /* perform rearranging on tracks list */ - rearrange_animchannel_islands(&adt->nla_tracks, rearrange_func, mode, ANIMTYPE_NLATRACK, &anim_data_visible); + /* perform rearranging on tracks list */ + rearrange_animchannel_islands( + &adt->nla_tracks, rearrange_func, mode, ANIMTYPE_NLATRACK, &anim_data_visible); - /* free temp data */ - BLI_freelistN(&anim_data_visible); + /* free temp data */ + BLI_freelistN(&anim_data_visible); } /* Drivers Specific Stuff ------------------------------------------------- */ @@ -1068,27 +1058,30 @@ static void rearrange_nla_channels(bAnimContext *ac, AnimData *adt, eRearrangeAn /* Change the order drivers within AnimData block * mode: REARRANGE_ANIMCHAN_* */ -static void rearrange_driver_channels(bAnimContext *ac, AnimData *adt, eRearrangeAnimChan_Mode mode) +static void rearrange_driver_channels(bAnimContext *ac, + AnimData *adt, + eRearrangeAnimChan_Mode mode) { - /* get rearranging function */ - AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode); - ListBase anim_data_visible = {NULL, NULL}; + /* get rearranging function */ + AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode); + ListBase anim_data_visible = {NULL, NULL}; - if (rearrange_func == NULL) - return; + if (rearrange_func == NULL) + return; - /* only consider drivers if they're accessible */ - if (EXPANDED_DRVD(adt) == 0) - return; + /* only consider drivers if they're accessible */ + if (EXPANDED_DRVD(adt) == 0) + return; - /* Filter visible data. */ - rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_FCURVE); + /* Filter visible data. */ + rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_FCURVE); - /* perform rearranging on drivers list (drivers are really just F-Curves) */ - rearrange_animchannel_islands(&adt->drivers, rearrange_func, mode, ANIMTYPE_FCURVE, &anim_data_visible); + /* perform rearranging on drivers list (drivers are really just F-Curves) */ + rearrange_animchannel_islands( + &adt->drivers, rearrange_func, mode, ANIMTYPE_FCURVE, &anim_data_visible); - /* free temp data */ - BLI_freelistN(&anim_data_visible); + /* free temp data */ + BLI_freelistN(&anim_data_visible); } /* Action Specific Stuff ------------------------------------------------- */ @@ -1096,88 +1089,88 @@ static void rearrange_driver_channels(bAnimContext *ac, AnimData *adt, eRearrang /* make sure all action-channels belong to a group (and clear action's list) */ static void split_groups_action_temp(bAction *act, bActionGroup *tgrp) { - bActionGroup *agrp; - FCurve *fcu; - - if (act == NULL) - return; - - /* Separate F-Curves into lists per group */ - 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.first; - fcu->prev = NULL; - - fcu = agrp->channels.last; - fcu->next = NULL; - } - } - - /* Initialize memory for temp-group */ - memset(tgrp, 0, sizeof(bActionGroup)); - 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; - - /* end of list */ - fcu = act->curves.last; - fcu->next = NULL; - tgrp->channels.last = fcu; - act->curves.last = NULL; - - /* ensure that all of these get their group set to this temp group - * (so that visibility filtering works) - */ - for (fcu = tgrp->channels.first; fcu; fcu = fcu->next) { - fcu->grp = tgrp; - } - } - - /* Add temp-group to list */ - BLI_addtail(&act->groups, tgrp); + bActionGroup *agrp; + FCurve *fcu; + + if (act == NULL) + return; + + /* Separate F-Curves into lists per group */ + 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.first; + fcu->prev = NULL; + + fcu = agrp->channels.last; + fcu->next = NULL; + } + } + + /* Initialize memory for temp-group */ + memset(tgrp, 0, sizeof(bActionGroup)); + 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; + + /* end of list */ + fcu = act->curves.last; + fcu->next = NULL; + tgrp->channels.last = fcu; + act->curves.last = NULL; + + /* ensure that all of these get their group set to this temp group + * (so that visibility filtering works) + */ + for (fcu = tgrp->channels.first; fcu; fcu = fcu->next) { + fcu->grp = tgrp; + } + } + + /* Add temp-group to list */ + BLI_addtail(&act->groups, tgrp); } /* link lists of channels that groups have */ static void join_groups_action_temp(bAction *act) { - bActionGroup *agrp; + bActionGroup *agrp; - for (agrp = act->groups.first; agrp; agrp = agrp->next) { - ListBase tempGroup; + for (agrp = act->groups.first; agrp; agrp = agrp->next) { + ListBase tempGroup; - /* add list of channels to action's channels */ - tempGroup = agrp->channels; - BLI_movelisttolist(&act->curves, &agrp->channels); - agrp->channels = tempGroup; + /* add list of channels to action's channels */ + tempGroup = agrp->channels; + BLI_movelisttolist(&act->curves, &agrp->channels); + agrp->channels = tempGroup; - /* clear moved flag */ - agrp->flag &= ~AGRP_MOVED; + /* clear moved flag */ + agrp->flag &= ~AGRP_MOVED; - /* if group was temporary one: - * - unassign all FCurves which were temporarily added to it - * - remove from list (but don't free as it's on the stack!) - */ - if (agrp->flag & AGRP_TEMP) { - FCurve *fcu; + /* if group was temporary one: + * - unassign all FCurves which were temporarily added to it + * - remove from list (but don't free as it's on the stack!) + */ + if (agrp->flag & AGRP_TEMP) { + FCurve *fcu; - for (fcu = agrp->channels.first; fcu; fcu = fcu->next) { - fcu->grp = NULL; - } + for (fcu = agrp->channels.first; fcu; fcu = fcu->next) { + fcu->grp = NULL; + } - BLI_remlink(&act->groups, agrp); - break; - } - } + BLI_remlink(&act->groups, agrp); + break; + } + } } /* Change the order of anim-channels within action @@ -1185,635 +1178,644 @@ static void join_groups_action_temp(bAction *act) */ static void rearrange_action_channels(bAnimContext *ac, bAction *act, eRearrangeAnimChan_Mode mode) { - bActionGroup tgrp; - ListBase anim_data_visible = {NULL, NULL}; - bool do_channels; + bActionGroup tgrp; + ListBase anim_data_visible = {NULL, NULL}; + bool do_channels; - /* get rearranging function */ - AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode); + /* get rearranging function */ + AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode); - if (rearrange_func == NULL) - return; + if (rearrange_func == NULL) + return; - /* make sure we're only operating with groups (vs a mixture of groups+curves) */ - split_groups_action_temp(act, &tgrp); + /* make sure we're only operating with groups (vs a mixture of groups+curves) */ + split_groups_action_temp(act, &tgrp); - /* Filter visible data. */ - rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_GROUP); + /* Filter visible data. */ + rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_GROUP); - /* rearrange groups first - * - the group's channels will only get considered if nothing happened when rearranging the groups - * i.e. the rearrange function returned 0 - */ - do_channels = (rearrange_animchannel_islands(&act->groups, rearrange_func, mode, ANIMTYPE_GROUP, - &anim_data_visible) == 0); + /* rearrange groups first + * - the group's channels will only get considered if nothing happened when rearranging the groups + * i.e. the rearrange function returned 0 + */ + do_channels = (rearrange_animchannel_islands( + &act->groups, rearrange_func, mode, ANIMTYPE_GROUP, &anim_data_visible) == 0); - /* free temp data */ - BLI_freelistN(&anim_data_visible); + /* free temp data */ + BLI_freelistN(&anim_data_visible); - if (do_channels) { - bActionGroup *agrp; + if (do_channels) { + bActionGroup *agrp; - /* Filter visible data. */ - rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_FCURVE); + /* Filter visible data. */ + rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_FCURVE); - for (agrp = act->groups.first; agrp; agrp = agrp->next) { - /* only consider F-Curves if they're visible (group expanded) */ - if (EXPANDED_AGRP(ac, agrp)) { - rearrange_animchannel_islands(&agrp->channels, rearrange_func, mode, ANIMTYPE_FCURVE, - &anim_data_visible); - } - } + 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, &anim_data_visible); + } + } - /* free temp data */ - BLI_freelistN(&anim_data_visible); - } + /* free temp data */ + BLI_freelistN(&anim_data_visible); + } - /* assemble lists into one list (and clear moved tags) */ - join_groups_action_temp(act); + /* assemble lists into one list (and clear moved tags) */ + join_groups_action_temp(act); } /* ------------------- */ -static void rearrange_nla_control_channels(bAnimContext *ac, AnimData *adt, eRearrangeAnimChan_Mode mode) +static void rearrange_nla_control_channels(bAnimContext *ac, + AnimData *adt, + eRearrangeAnimChan_Mode mode) { - ListBase anim_data_visible = {NULL, NULL}; + ListBase anim_data_visible = {NULL, NULL}; - NlaTrack *nlt; - NlaStrip *strip; + NlaTrack *nlt; + NlaStrip *strip; - /* get rearranging function */ - AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode); + /* get rearranging function */ + AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode); - if (rearrange_func == NULL) - return; + if (rearrange_func == NULL) + return; - /* skip if these curves aren't being shown */ - if (adt->flag & ADT_NLA_SKEYS_COLLAPSED) - return; + /* skip if these curves aren't being shown */ + if (adt->flag & ADT_NLA_SKEYS_COLLAPSED) + return; - /* Filter visible data. */ - rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_NLACURVE); + /* Filter visible data. */ + rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_NLACURVE); - /* we cannot rearrange between strips, but within each strip, we can rearrange those curves */ - for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { - for (strip = nlt->strips.first; strip; strip = strip->next) { - rearrange_animchannel_islands( - &strip->fcurves, rearrange_func, mode, ANIMTYPE_NLACURVE, - &anim_data_visible); - } - } + /* we cannot rearrange between strips, but within each strip, we can rearrange those curves */ + for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { + for (strip = nlt->strips.first; strip; strip = strip->next) { + rearrange_animchannel_islands( + &strip->fcurves, rearrange_func, mode, ANIMTYPE_NLACURVE, &anim_data_visible); + } + } - /* free temp data */ - BLI_freelistN(&anim_data_visible); + /* free temp data */ + BLI_freelistN(&anim_data_visible); } /* ------------------- */ static void rearrange_gpencil_channels(bAnimContext *ac, eRearrangeAnimChan_Mode mode) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; - /* get rearranging function */ - AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode); + /* get rearranging function */ + AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode); - if (rearrange_func == NULL) - return; + if (rearrange_func == NULL) + return; - /* get Grease Pencil datablocks */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + /* get Grease Pencil datablocks */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - for (ale = anim_data.first; ale; ale = ale->next) { - ListBase anim_data_visible = {NULL, NULL}; - bGPdata *gpd = ale->data; + for (ale = anim_data.first; ale; ale = ale->next) { + ListBase anim_data_visible = {NULL, NULL}; + bGPdata *gpd = ale->data; - /* only consider layers if this datablock is open */ - BLI_assert(ale->type == ANIMTYPE_GPDATABLOCK); - if ((gpd->flag & GP_DATA_EXPAND) == 0) - continue; + /* only consider layers if this datablock is open */ + BLI_assert(ale->type == ANIMTYPE_GPDATABLOCK); + if ((gpd->flag & GP_DATA_EXPAND) == 0) + continue; - /* Filter visible data. */ - rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_GPLAYER); + /* Filter visible data. */ + rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_GPLAYER); - /* rearrange datablock's layers */ - rearrange_animchannel_islands(&gpd->layers, rearrange_func, mode, ANIMTYPE_GPLAYER, &anim_data_visible); + /* rearrange datablock's layers */ + rearrange_animchannel_islands( + &gpd->layers, rearrange_func, mode, ANIMTYPE_GPLAYER, &anim_data_visible); - /* free visible layers data */ - BLI_freelistN(&anim_data_visible); - } + /* free visible layers data */ + BLI_freelistN(&anim_data_visible); + } - /* free GPD channel data */ - ANIM_animdata_freelist(&anim_data); + /* free GPD channel data */ + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ static int animchannels_rearrange_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - eRearrangeAnimChan_Mode mode; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* get mode */ - mode = RNA_enum_get(op->ptr, "direction"); - - /* method to move channels depends on the editor */ - if (ac.datatype == ANIMCONT_GPENCIL) { - /* Grease Pencil channels */ - rearrange_gpencil_channels(&ac, mode); - } - 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); - } - else { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - /* get animdata blocks */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - for (ale = anim_data.first; ale; ale = ale->next) { - AnimData *adt = ale->data; - - switch (ac.datatype) { - case ANIMCONT_NLA: /* NLA-tracks only */ - rearrange_nla_channels(&ac, adt, mode); - DEG_id_tag_update(ale->id, ID_RECALC_ANIMATION); - break; - - case ANIMCONT_DRIVERS: /* Drivers list only */ - rearrange_driver_channels(&ac, adt, mode); - break; - - case ANIMCONT_ACTION: /* Single Action only... */ - case ANIMCONT_SHAPEKEY: // DOUBLE CHECK ME... - { - if (adt->action) - rearrange_action_channels(&ac, adt->action, mode); - else if (G.debug & G_DEBUG) - printf("Animdata has no action\n"); - break; - } - - default: /* DopeSheet/Graph Editor - Some Actions + NLA Control Curves */ - { - /* NLA Control Curves */ - if (adt->nla_tracks.first) - rearrange_nla_control_channels(&ac, adt, mode); - - /* Action */ - if (adt->action) - rearrange_action_channels(&ac, adt->action, mode); - else if (G.debug & G_DEBUG) - printf("Animdata has no action\n"); - break; - } - } - } - - /* free temp data */ - ANIM_animdata_freelist(&anim_data); - } - - /* send notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - - return OPERATOR_FINISHED; + bAnimContext ac; + eRearrangeAnimChan_Mode mode; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get mode */ + mode = RNA_enum_get(op->ptr, "direction"); + + /* method to move channels depends on the editor */ + if (ac.datatype == ANIMCONT_GPENCIL) { + /* Grease Pencil channels */ + rearrange_gpencil_channels(&ac, mode); + } + 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); + } + else { + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* get animdata blocks */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt = ale->data; + + switch (ac.datatype) { + case ANIMCONT_NLA: /* NLA-tracks only */ + rearrange_nla_channels(&ac, adt, mode); + DEG_id_tag_update(ale->id, ID_RECALC_ANIMATION); + break; + + case ANIMCONT_DRIVERS: /* Drivers list only */ + rearrange_driver_channels(&ac, adt, mode); + break; + + case ANIMCONT_ACTION: /* Single Action only... */ + case ANIMCONT_SHAPEKEY: // DOUBLE CHECK ME... + { + if (adt->action) + rearrange_action_channels(&ac, adt->action, mode); + else if (G.debug & G_DEBUG) + printf("Animdata has no action\n"); + break; + } + + default: /* DopeSheet/Graph Editor - Some Actions + NLA Control Curves */ + { + /* NLA Control Curves */ + if (adt->nla_tracks.first) + rearrange_nla_control_channels(&ac, adt, mode); + + /* Action */ + if (adt->action) + rearrange_action_channels(&ac, adt->action, mode); + else if (G.debug & G_DEBUG) + printf("Animdata has no action\n"); + break; + } + } + } + + /* free temp data */ + ANIM_animdata_freelist(&anim_data); + } + + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + + return OPERATOR_FINISHED; } static void ANIM_OT_channels_move(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Move Channels"; - ot->idname = "ANIM_OT_channels_move"; - ot->description = "Rearrange selected animation channels"; + /* identifiers */ + 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; + /* api callbacks */ + ot->exec = animchannels_rearrange_exec; + ot->poll = animedit_poll_channels_nla_tweakmode_off; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* props */ - ot->prop = RNA_def_enum(ot->srna, "direction", prop_animchannel_rearrange_types, REARRANGE_ANIMCHAN_DOWN, "Direction", ""); + /* props */ + ot->prop = RNA_def_enum(ot->srna, + "direction", + prop_animchannel_rearrange_types, + REARRANGE_ANIMCHAN_DOWN, + "Direction", + ""); } /* ******************** Group Channel Operator ************************ */ static bool animchannels_grouping_poll(bContext *C) { - ScrArea *sa = CTX_wm_area(C); - SpaceLink *sl; + 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; + /* 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); + /* 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; + 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; + /* 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_GRAPH: - { - SpaceGraph *sipo = (SpaceGraph *)sl; + break; + } + case SPACE_GRAPH: { + SpaceGraph *sipo = (SpaceGraph *)sl; - /* drivers can't have groups... */ - if (sipo->mode != SIPO_MODE_ANIMATION) - return 0; + /* drivers can't have groups... */ + if (sipo->mode != SIPO_MODE_ANIMATION) + return 0; - break; - } - /* unsupported... */ - default: - return 0; - } + break; + } + /* unsupported... */ + default: + return 0; + } - return 1; + return 1; } /* ----------------------------------------------------------- */ -static void animchannels_group_channels(bAnimContext *ac, bAnimListElem *adt_ref, const char name[]) +static void animchannels_group_channels(bAnimContext *ac, + bAnimListElem *adt_ref, + const char name[]) { - AnimData *adt = adt_ref->adt; - bAction *act = adt->action; + AnimData *adt = adt_ref->adt; + bAction *act = adt->action; - if (act) { - ListBase anim_data = {NULL, NULL}; - int filter; + 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); + /* 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; + 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); + /* 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; + /* 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); + /* remove F-Curve from group, then group too if it is now empty */ + action_groups_remove_channel(act, fcu); - if ((grp) && BLI_listbase_is_empty(&grp->channels)) { - BLI_freelinkN(&act->groups, grp); - } + if ((grp) && BLI_listbase_is_empty(&grp->channels)) { + BLI_freelinkN(&act->groups, grp); + } - /* add F-Curve to group */ - action_groups_add_channel(act, agrp, fcu); - } - } + /* add F-Curve to group */ + action_groups_add_channel(act, agrp, fcu); + } + } - /* cleanup */ - ANIM_animdata_freelist(&anim_data); - } + /* cleanup */ + ANIM_animdata_freelist(&anim_data); + } } static int animchannels_group_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - char name[MAX_NAME]; + bAnimContext ac; + char name[MAX_NAME]; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* 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); + /* 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; + /* 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); + /* 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); - } + for (ale = anim_data.first; ale; ale = ale->next) { + animchannels_group_channels(&ac, ale, name); + } - /* free temp data */ - ANIM_animdata_freelist(&anim_data); + /* free temp data */ + ANIM_animdata_freelist(&anim_data); - /* updatss */ - WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - } + /* updatss */ + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + } - return OPERATOR_FINISHED; + 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"; + /* 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; + /* callbacks */ + ot->invoke = WM_operator_props_popup; + ot->exec = animchannels_group_exec; + ot->poll = animchannels_grouping_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* props */ - ot->prop = RNA_def_string(ot->srna, "name", "New Group", - sizeof(((bActionGroup *)NULL)->name), - "Name", "Name of newly created group"); - /* XXX: still not too sure about this - keeping same text is confusing... */ - // RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); + /* props */ + ot->prop = RNA_def_string(ot->srna, + "name", + "New Group", + sizeof(((bActionGroup *)NULL)->name), + "Name", + "Name of newly created group"); + /* XXX: still not too sure about this - keeping same text is confusing... */ + // RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); } /* ----------------------------------------------------------- */ static int animchannels_ungroup_exec(bContext *C, wmOperator *UNUSED(op)) { - bAnimContext ac; + bAnimContext ac; - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* 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); + /* 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; + 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; + /* 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); + /* 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 (BLI_listbase_is_empty(&agrp->channels)) { - BLI_freelinkN(&act->groups, agrp); - } - } - } - } + /* delete group if it is now empty */ + if (BLI_listbase_is_empty(&agrp->channels)) { + BLI_freelinkN(&act->groups, agrp); + } + } + } + } - /* cleanup */ - ANIM_animdata_freelist(&anim_data); + /* cleanup */ + ANIM_animdata_freelist(&anim_data); - /* updates */ - WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + /* updates */ + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - return OPERATOR_FINISHED; + 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"; + /* 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; + /* callbacks */ + ot->exec = animchannels_ungroup_exec; + ot->poll = animchannels_grouping_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************** Delete Channel Operator *********************** */ static void update_dependencies_on_delete(bAnimListElem *ale) { - ID *id = ale->id; - AnimData *adt = BKE_animdata_from_id(id); - /* TODO(sergey): Technically, if the animation element is being deleted - * from a driver we don't have to tag action. This is something we can check - * for in the future. For now just do most reliable tag whic hwas always - * happening. */ - if (adt != NULL) { - DEG_id_tag_update(id, ID_RECALC_ANIMATION); - if (adt->action != NULL) { - DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION); - } - } - /* Deals with NLA and drivers. - * Doesn't cause overhead for action updates, since object will receive - * animation update after dependency graph flushes update from action to - * all its users. */ - DEG_id_tag_update(id, ID_RECALC_ANIMATION); + ID *id = ale->id; + AnimData *adt = BKE_animdata_from_id(id); + /* TODO(sergey): Technically, if the animation element is being deleted + * from a driver we don't have to tag action. This is something we can check + * for in the future. For now just do most reliable tag whic hwas always + * happening. */ + if (adt != NULL) { + DEG_id_tag_update(id, ID_RECALC_ANIMATION); + if (adt->action != NULL) { + DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION); + } + } + /* Deals with NLA and drivers. + * Doesn't cause overhead for action updates, since object will receive + * animation update after dependency graph flushes update from action to + * all its users. */ + DEG_id_tag_update(id, ID_RECALC_ANIMATION); } static int animchannels_delete_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; - - /* cannot delete in shapekey */ - if (ac.datatype == ANIMCONT_SHAPEKEY) - return OPERATOR_CANCELLED; - - - /* 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); - 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) { - /* 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; - FCurve *fcu, *fcn; - - /* skip this group if no AnimData available, as we can't safely remove the F-Curves */ - if (adt == NULL) - 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; - - /* remove from group and action, then free */ - action_groups_remove_channel(adt->action, fcu); - free_fcurve(fcu); - } - - /* free the group itself */ - if (adt->action) { - BLI_freelinkN(&adt->action->groups, agrp); - DEG_id_tag_update_ex(CTX_data_main(C), &adt->action->id, ID_RECALC_ANIMATION); - } - else - MEM_freeN(agrp); - } - } - - /* cleanup */ - ANIM_animdata_freelist(&anim_data); - } - - /* filter data */ - 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) { - switch (ale->type) { - case ANIMTYPE_FCURVE: - { - /* F-Curves if we can identify its parent */ - AnimData *adt = ale->adt; - FCurve *fcu = (FCurve *)ale->data; - - /* try to free F-Curve */ - ANIM_fcurve_delete_from_animdata(&ac, adt, fcu); - update_dependencies_on_delete(ale); - break; - } - case ANIMTYPE_NLACURVE: - { - /* NLA Control Curve - Deleting it should disable the corresponding setting... */ - NlaStrip *strip = (NlaStrip *)ale->owner; - FCurve *fcu = (FCurve *)ale->data; - - if (STREQ(fcu->rna_path, "strip_time")) { - strip->flag &= ~NLASTRIP_FLAG_USR_TIME; - } - else if (STREQ(fcu->rna_path, "influence")) { - strip->flag &= ~NLASTRIP_FLAG_USR_INFLUENCE; - } - else { - printf("ERROR: Trying to delete NLA Control Curve for unknown property '%s'\n", fcu->rna_path); - } - - /* unlink and free the F-Curve */ - BLI_remlink(&strip->fcurves, fcu); - free_fcurve(fcu); - update_dependencies_on_delete(ale); - break; - } - case ANIMTYPE_GPLAYER: - { - /* Grease Pencil layer */ - bGPdata *gpd = (bGPdata *)ale->id; - bGPDlayer *gpl = (bGPDlayer *)ale->data; - - /* try to delete the layer's data and the layer itself */ - BKE_gpencil_layer_delete(gpd, gpl); - ale->update = ANIM_UPDATE_DEPS; - 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; - } - } - } - - /* cleanup */ - ANIM_animdata_freelist(&anim_data); - - /* send notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - DEG_relations_tag_update(CTX_data_main(C)); - - return OPERATOR_FINISHED; + 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; + + /* cannot delete in shapekey */ + if (ac.datatype == ANIMCONT_SHAPEKEY) + return OPERATOR_CANCELLED; + + /* 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); + 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) { + /* 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; + FCurve *fcu, *fcn; + + /* skip this group if no AnimData available, as we can't safely remove the F-Curves */ + if (adt == NULL) + 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; + + /* remove from group and action, then free */ + action_groups_remove_channel(adt->action, fcu); + free_fcurve(fcu); + } + + /* free the group itself */ + if (adt->action) { + BLI_freelinkN(&adt->action->groups, agrp); + DEG_id_tag_update_ex(CTX_data_main(C), &adt->action->id, ID_RECALC_ANIMATION); + } + else + MEM_freeN(agrp); + } + } + + /* cleanup */ + ANIM_animdata_freelist(&anim_data); + } + + /* filter data */ + 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) { + switch (ale->type) { + case ANIMTYPE_FCURVE: { + /* F-Curves if we can identify its parent */ + AnimData *adt = ale->adt; + FCurve *fcu = (FCurve *)ale->data; + + /* try to free F-Curve */ + ANIM_fcurve_delete_from_animdata(&ac, adt, fcu); + update_dependencies_on_delete(ale); + break; + } + case ANIMTYPE_NLACURVE: { + /* NLA Control Curve - Deleting it should disable the corresponding setting... */ + NlaStrip *strip = (NlaStrip *)ale->owner; + FCurve *fcu = (FCurve *)ale->data; + + if (STREQ(fcu->rna_path, "strip_time")) { + strip->flag &= ~NLASTRIP_FLAG_USR_TIME; + } + else if (STREQ(fcu->rna_path, "influence")) { + strip->flag &= ~NLASTRIP_FLAG_USR_INFLUENCE; + } + else { + printf("ERROR: Trying to delete NLA Control Curve for unknown property '%s'\n", + fcu->rna_path); + } + + /* unlink and free the F-Curve */ + BLI_remlink(&strip->fcurves, fcu); + free_fcurve(fcu); + update_dependencies_on_delete(ale); + break; + } + case ANIMTYPE_GPLAYER: { + /* Grease Pencil layer */ + bGPdata *gpd = (bGPdata *)ale->id; + bGPDlayer *gpl = (bGPDlayer *)ale->data; + + /* try to delete the layer's data and the layer itself */ + BKE_gpencil_layer_delete(gpd, gpl); + ale->update = ANIM_UPDATE_DEPS; + 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; + } + } + } + + /* cleanup */ + ANIM_animdata_freelist(&anim_data); + + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + DEG_relations_tag_update(CTX_data_main(C)); + + return OPERATOR_FINISHED; } 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"; + /* identifiers */ + 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; + /* api callbacks */ + ot->exec = animchannels_delete_exec; + ot->poll = animedit_poll_channels_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ********************** Set Flags Operator *********************** */ /* defines for setting animation-channel flags */ static const EnumPropertyItem prop_animchannel_setflag_types[] = { - {ACHANNEL_SETFLAG_TOGGLE, "TOGGLE", 0, "Toggle", ""}, - {ACHANNEL_SETFLAG_CLEAR, "DISABLE", 0, "Disable", ""}, - {ACHANNEL_SETFLAG_ADD, "ENABLE", 0, "Enable", ""}, - {ACHANNEL_SETFLAG_INVERT, "INVERT", 0, "Invert", ""}, - {0, NULL, 0, NULL, NULL}, + {ACHANNEL_SETFLAG_TOGGLE, "TOGGLE", 0, "Toggle", ""}, + {ACHANNEL_SETFLAG_CLEAR, "DISABLE", 0, "Disable", ""}, + {ACHANNEL_SETFLAG_ADD, "ENABLE", 0, "Enable", ""}, + {ACHANNEL_SETFLAG_INVERT, "INVERT", 0, "Invert", ""}, + {0, NULL, 0, NULL, NULL}, }; /* defines for set animation-channel settings */ // TODO: could add some more types, but those are really quite dependent on the mode... static const EnumPropertyItem prop_animchannel_settings_types[] = { - {ACHANNEL_SETTING_PROTECT, "PROTECT", 0, "Protect", ""}, - {ACHANNEL_SETTING_MUTE, "MUTE", 0, "Mute", ""}, - {0, NULL, 0, NULL, NULL}, + {ACHANNEL_SETTING_PROTECT, "PROTECT", 0, "Protect", ""}, + {ACHANNEL_SETTING_MUTE, "MUTE", 0, "Mute", ""}, + {0, NULL, 0, NULL, NULL}, }; - /* ------------------- */ /* Set/clear a particular flag (setting) for all selected + visible channels @@ -1822,288 +1824,302 @@ static const 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, eAnimChannel_Settings setting, eAnimChannels_SetFlag mode, bool onlysel, bool flush) -{ - ListBase anim_data = {NULL, NULL}; - ListBase all_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - /* filter data that we need if flush is on */ - if (flush) { - /* get list of all channels that selection may need to be flushed to - * - hierarchy visibility needs to be ignored so that settings can get flushed - * "down" inside closed containers - */ - filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS; - ANIM_animdata_filter(ac, &all_data, filter, ac->data, ac->datatype); - } - - /* filter data that we're working on - * - hierarchy matters if we're doing this from the channels region - * since we only want to apply this to channels we can "see", - * and have these affect their relatives - * - but for Graph Editor, this gets used also from main region - * where hierarchy doesn't apply [#21276] - */ - if ((ac->spacetype == SPACE_GRAPH) && (ac->regiontype != RGN_TYPE_CHANNELS)) { - /* graph editor (case 2) */ - 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); - } - if (onlysel) filter |= ANIMFILTER_SEL; - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* 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; - - /* see if we should turn off instead... */ - 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; - break; - } - } - } - - /* apply the setting */ - 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; - - /* set the setting in the appropriate way */ - ANIM_channel_setting_set(ac, ale, setting, mode); - - /* if flush status... */ - if (flush) - ANIM_flush_setting_anim_channels(ac, &all_data, ale, setting, mode); - } - - ANIM_animdata_freelist(&anim_data); - BLI_freelistN(&all_data); +static void setflag_anim_channels(bAnimContext *ac, + eAnimChannel_Settings setting, + eAnimChannels_SetFlag mode, + bool onlysel, + bool flush) +{ + ListBase anim_data = {NULL, NULL}; + ListBase all_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* filter data that we need if flush is on */ + if (flush) { + /* get list of all channels that selection may need to be flushed to + * - hierarchy visibility needs to be ignored so that settings can get flushed + * "down" inside closed containers + */ + filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS; + ANIM_animdata_filter(ac, &all_data, filter, ac->data, ac->datatype); + } + + /* filter data that we're working on + * - hierarchy matters if we're doing this from the channels region + * since we only want to apply this to channels we can "see", + * and have these affect their relatives + * - but for Graph Editor, this gets used also from main region + * where hierarchy doesn't apply [#21276] + */ + if ((ac->spacetype == SPACE_GRAPH) && (ac->regiontype != RGN_TYPE_CHANNELS)) { + /* graph editor (case 2) */ + 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); + } + if (onlysel) + filter |= ANIMFILTER_SEL; + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* 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; + + /* see if we should turn off instead... */ + 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; + break; + } + } + } + + /* apply the setting */ + 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; + + /* set the setting in the appropriate way */ + ANIM_channel_setting_set(ac, ale, setting, mode); + + /* if flush status... */ + if (flush) + ANIM_flush_setting_anim_channels(ac, &all_data, ale, setting, mode); + } + + ANIM_animdata_freelist(&anim_data); + BLI_freelistN(&all_data); } /* ------------------- */ static int animchannels_setflag_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - eAnimChannel_Settings setting; - eAnimChannels_SetFlag mode; - bool flush = true; + bAnimContext ac; + eAnimChannel_Settings setting; + eAnimChannels_SetFlag mode; + bool flush = true; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* 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 (eAnimChannels_SetFlag), setting (eAnimChannel_Settings) */ + 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 = false; + /* check if setting is flushable */ + if (setting == ACHANNEL_SETTING_EXPAND) + flush = false; - /* modify setting - * - only selected channels are affected - */ - setflag_anim_channels(&ac, setting, mode, true, flush); + /* modify setting + * - only selected channels are affected + */ + setflag_anim_channels(&ac, setting, mode, true, flush); - /* send notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } /* duplicate of 'ANIM_OT_channels_setting_toggle' for menu title only, weak! */ static void ANIM_OT_channels_setting_enable(wmOperatorType *ot) { - PropertyRNA *prop; + 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"; + /* identifiers */ + 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; + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = animchannels_setflag_exec; + ot->poll = animedit_poll_channels_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* props */ - /* 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", ""); + /* props */ + /* 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) { - PropertyRNA *prop; + 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"; + /* identifiers */ + 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; + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = animchannels_setflag_exec; + ot->poll = animedit_poll_channels_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* props */ - /* 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", ""); + /* props */ + /* 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) { - PropertyRNA *prop; + 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"; + /* identifiers */ + 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; + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = animchannels_setflag_exec; + ot->poll = animedit_poll_channels_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* props */ - /* 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", ""); + /* props */ + /* 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) { - PropertyRNA *prop; + PropertyRNA *prop; - /* identifiers */ - ot->name = "Toggle Channel Editability"; - ot->idname = "ANIM_OT_channels_editable_toggle"; - ot->description = "Toggle editability of selected channels"; + /* identifiers */ + 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; + /* api callbacks */ + ot->exec = animchannels_setflag_exec; + ot->poll = animedit_poll_channels_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + 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 */ - 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 */ + /* props */ + /* flag-setting mode */ + RNA_def_enum( + ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", ""); + /* 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) { - bAnimContext ac; - bool onlysel = true; + bAnimContext ac; + bool onlysel = true; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* only affect selected channels? */ - if (RNA_boolean_get(op->ptr, "all")) - onlysel = false; + /* only affect selected channels? */ + if (RNA_boolean_get(op->ptr, "all")) + onlysel = false; - /* modify setting */ - setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_ADD, onlysel, false); + /* modify setting */ + setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_ADD, onlysel, false); - /* send notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } 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"; + /* identifiers */ + 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; + /* api callbacks */ + ot->exec = animchannels_expand_exec; + ot->poll = animedit_poll_channels_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* props */ - ot->prop = RNA_def_boolean(ot->srna, "all", 1, "All", "Expand all channels (not just selected ones)"); + /* props */ + 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) { - bAnimContext ac; - bool onlysel = true; + bAnimContext ac; + bool onlysel = true; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* only affect selected channels? */ - if (RNA_boolean_get(op->ptr, "all")) - onlysel = false; + /* only affect selected channels? */ + if (RNA_boolean_get(op->ptr, "all")) + onlysel = false; - /* modify setting */ - setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_CLEAR, onlysel, false); + /* modify setting */ + setflag_anim_channels(&ac, ACHANNEL_SETTING_EXPAND, ACHANNEL_SETFLAG_CLEAR, onlysel, false); - /* send notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } 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"; + /* identifiers */ + 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; + /* api callbacks */ + ot->exec = animchannels_collapse_exec; + ot->poll = animedit_poll_channels_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* props */ - ot->prop = RNA_def_boolean(ot->srna, "all", true, "All", "Collapse all channels (not just selected ones)"); + /* props */ + ot->prop = RNA_def_boolean( + ot->srna, "all", true, "All", "Collapse all channels (not just selected ones)"); } /* ************ Remove All "Empty" AnimData Blocks Operator ********* */ @@ -2120,170 +2136,169 @@ static void ANIM_OT_channels_collapse(wmOperatorType *ot) static int animchannels_clean_empty_exec(bContext *C, wmOperator *UNUSED(op)) { - bAnimContext ac; - - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* get animdata blocks */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - for (ale = anim_data.first; ale; ale = ale->next) { - ID *id = ale->id; - AnimData *adt = ale->data; - - bool action_empty = false; - bool nla_empty = false; - bool drivers_empty = false; - - /* sanity checks */ - BLI_assert((id != NULL) && (adt != NULL)); - - /* check if this is "empty" and can be deleted */ - /* (For now, there are only these 3 criteria) */ - - /* 1) Active Action is missing or empty */ - if (ELEM(NULL, adt->action, adt->action->curves.first)) { - action_empty = true; - } - else { - /* TODO: check for keyframe + fmodifier data on these too */ - } - - /* 2) No NLA Tracks and/or NLA Strips */ - if (adt->nla_tracks.first == NULL) { - nla_empty = true; - } - else { - NlaTrack *nlt; - - /* empty tracks? */ - for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { - if (nlt->strips.first) { - /* stop searching, as we found one that actually had stuff we don't want lost - * NOTE: nla_empty gets reset to false, as a previous track may have been empty - */ - nla_empty = false; - break; - } - else if (nlt->strips.first == NULL) { - /* this track is empty, but another one may still have stuff in it, so can't break yet */ - nla_empty = true; - } - } - } - - /* 3) Drivers */ - drivers_empty = (adt->drivers.first == NULL); - - - /* remove AnimData? */ - if (action_empty && nla_empty && drivers_empty) { - BKE_animdata_free(id, true); - } - } - - /* free temp data */ - ANIM_animdata_freelist(&anim_data); - - /* send notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - - return OPERATOR_FINISHED; + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get animdata blocks */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + for (ale = anim_data.first; ale; ale = ale->next) { + ID *id = ale->id; + AnimData *adt = ale->data; + + bool action_empty = false; + bool nla_empty = false; + bool drivers_empty = false; + + /* sanity checks */ + BLI_assert((id != NULL) && (adt != NULL)); + + /* check if this is "empty" and can be deleted */ + /* (For now, there are only these 3 criteria) */ + + /* 1) Active Action is missing or empty */ + if (ELEM(NULL, adt->action, adt->action->curves.first)) { + action_empty = true; + } + else { + /* TODO: check for keyframe + fmodifier data on these too */ + } + + /* 2) No NLA Tracks and/or NLA Strips */ + if (adt->nla_tracks.first == NULL) { + nla_empty = true; + } + else { + NlaTrack *nlt; + + /* empty tracks? */ + for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { + if (nlt->strips.first) { + /* stop searching, as we found one that actually had stuff we don't want lost + * NOTE: nla_empty gets reset to false, as a previous track may have been empty + */ + nla_empty = false; + break; + } + else if (nlt->strips.first == NULL) { + /* this track is empty, but another one may still have stuff in it, so can't break yet */ + nla_empty = true; + } + } + } + + /* 3) Drivers */ + drivers_empty = (adt->drivers.first == NULL); + + /* remove AnimData? */ + if (action_empty && nla_empty && drivers_empty) { + BKE_animdata_free(id, true); + } + } + + /* free temp data */ + ANIM_animdata_freelist(&anim_data); + + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + + return OPERATOR_FINISHED; } static void ANIM_OT_channels_clean_empty(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Remove Empty Animation Data"; - ot->idname = "ANIM_OT_channels_clean_empty"; - ot->description = "Delete all empty animation data containers from visible data-blocks"; + /* identifiers */ + ot->name = "Remove Empty Animation Data"; + ot->idname = "ANIM_OT_channels_clean_empty"; + ot->description = "Delete all empty animation data containers from visible data-blocks"; - /* api callbacks */ - ot->exec = animchannels_clean_empty_exec; - ot->poll = animedit_poll_channels_nla_tweakmode_off; + /* api callbacks */ + ot->exec = animchannels_clean_empty_exec; + ot->poll = animedit_poll_channels_nla_tweakmode_off; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************* Reenable Disabled Operator ******************* */ static bool 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? */ - if (ELEM(NULL, sa, CTX_wm_region(C))) - return 0; + /* 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 - Action/Dopesheet/etc. and Graph only */ - if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH) == 0) - return 0; + /* animation editor test - Action/Dopesheet/etc. and Graph only */ + if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH) == 0) + return 0; - return 1; + return 1; } static int animchannels_enable_exec(bContext *C, wmOperator *UNUSED(op)) { - bAnimContext ac; + bAnimContext ac; - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + /* filter data */ + 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) { - FCurve *fcu = (FCurve *)ale->data; + /* loop through filtered data and clean curves */ + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->data; - /* remove disabled flags from F-Curves */ - fcu->flag &= ~FCURVE_DISABLED; + /* remove disabled flags from F-Curves */ + fcu->flag &= ~FCURVE_DISABLED; - /* for drivers, let's do the same too */ - if (fcu->driver) - fcu->driver->flag &= ~DRIVER_FLAG_INVALID; + /* for drivers, let's do the same too */ + if (fcu->driver) + fcu->driver->flag &= ~DRIVER_FLAG_INVALID; - /* tag everything for updates - in particular, this is needed to get drivers working again */ - ale->update |= ANIM_UPDATE_DEPS; - } + /* tag everything for updates - in particular, this is needed to get drivers working again */ + ale->update |= ANIM_UPDATE_DEPS; + } - ANIM_animdata_update(&ac, &anim_data); - ANIM_animdata_freelist(&anim_data); + ANIM_animdata_update(&ac, &anim_data); + ANIM_animdata_freelist(&anim_data); - /* send notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } 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"; + /* 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"; - /* api callbacks */ - ot->exec = animchannels_enable_exec; - ot->poll = animchannels_enable_poll; + /* api callbacks */ + ot->exec = animchannels_enable_exec; + ot->poll = animchannels_enable_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ****************** Find / Set Filter Operator ******************** */ @@ -2291,253 +2306,256 @@ static void ANIM_OT_channels_fcurves_enable(wmOperatorType *ot) /* XXX: make this generic? */ static bool animchannels_find_poll(bContext *C) { - ScrArea *sa = CTX_wm_area(C); + ScrArea *sa = CTX_wm_area(C); - if (sa == NULL) - return 0; + if (sa == NULL) + return 0; - /* animation editor with dopesheet */ - return ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA); + /* animation editor with dopesheet */ + return ELEM(sa->spacetype, SPACE_ACTION, SPACE_GRAPH, SPACE_NLA); } /* find_invoke() - Get initial channels */ static int animchannels_find_invoke(bContext *C, wmOperator *op, const wmEvent *evt) { - bAnimContext ac; + bAnimContext ac; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* set initial filter text, and enable filter */ - RNA_string_set(op->ptr, "query", ac.ads->searchstr); + /* set initial filter text, and enable filter */ + RNA_string_set(op->ptr, "query", ac.ads->searchstr); - /* defer to popup */ - return WM_operator_props_popup(C, op, evt); + /* defer to popup */ + return WM_operator_props_popup(C, op, evt); } /* find_exec() - Called to set the value */ static int animchannels_find_exec(bContext *C, wmOperator *op) { - bAnimContext ac; + bAnimContext ac; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* update filter text */ - RNA_string_get(op->ptr, "query", ac.ads->searchstr); + /* update filter text */ + RNA_string_get(op->ptr, "query", ac.ads->searchstr); - /* redraw */ - WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + /* redraw */ + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static void ANIM_OT_channels_find(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Find Channels"; - ot->idname = "ANIM_OT_channels_find"; - ot->description = "Filter the set of channels shown to only include those with matching names"; + /* identifiers */ + ot->name = "Find Channels"; + ot->idname = "ANIM_OT_channels_find"; + ot->description = "Filter the set of channels shown to only include those with matching names"; - /* callbacks */ - ot->invoke = animchannels_find_invoke; - ot->exec = animchannels_find_exec; - ot->poll = animchannels_find_poll; + /* callbacks */ + ot->invoke = animchannels_find_invoke; + ot->exec = animchannels_find_exec; + ot->poll = animchannels_find_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - ot->prop = RNA_def_string(ot->srna, "query", "Query", sizeof(((bDopeSheet *)NULL)->searchstr), "", "Text to search for in channel names"); + /* properties */ + ot->prop = RNA_def_string(ot->srna, + "query", + "Query", + sizeof(((bDopeSheet *)NULL)->searchstr), + "", + "Text to search for in channel names"); } /* ********************** Select All Operator *********************** */ static int animchannels_deselectall_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* 'standard' behavior - check if selected, then apply relevant selection */ - const int action = RNA_enum_get(op->ptr, "action"); - switch (action) { - case SEL_TOGGLE: - ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, true, ACHANNEL_SETFLAG_ADD); - break; - case SEL_SELECT: - ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, false, ACHANNEL_SETFLAG_ADD); - break; - case SEL_DESELECT: - ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, false, ACHANNEL_SETFLAG_CLEAR); - break; - case SEL_INVERT: - ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, false, ACHANNEL_SETFLAG_INVERT); - break; - default: - BLI_assert(0); - break; - } - - /* send notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL); - - return OPERATOR_FINISHED; + bAnimContext ac; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* 'standard' behavior - check if selected, then apply relevant selection */ + const int action = RNA_enum_get(op->ptr, "action"); + switch (action) { + case SEL_TOGGLE: + ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, true, ACHANNEL_SETFLAG_ADD); + break; + case SEL_SELECT: + ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, false, ACHANNEL_SETFLAG_ADD); + break; + case SEL_DESELECT: + ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, false, ACHANNEL_SETFLAG_CLEAR); + break; + case SEL_INVERT: + ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, false, ACHANNEL_SETFLAG_INVERT); + break; + default: + BLI_assert(0); + break; + } + + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL); + + return OPERATOR_FINISHED; } static void ANIM_OT_channels_select_all(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Select All"; - ot->idname = "ANIM_OT_channels_select_all"; - ot->description = "Toggle selection of all animation channels"; + /* identifiers */ + ot->name = "Select All"; + ot->idname = "ANIM_OT_channels_select_all"; + ot->description = "Toggle selection of all animation channels"; - /* api callbacks */ - ot->exec = animchannels_deselectall_exec; - ot->poll = animedit_poll_channels_nla_tweakmode_off; + /* api callbacks */ + ot->exec = animchannels_deselectall_exec; + ot->poll = animedit_poll_channels_nla_tweakmode_off; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - WM_operator_properties_select_all(ot); + /* properties */ + WM_operator_properties_select_all(ot); } /* ******************** Box Select Operator *********************** */ static void box_select_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; - rctf rectf; - float ymin, ymax; - - /* set initial y extents */ - if (ac->datatype == ANIMCONT_NLA) { - ymin = (float)(-NLACHANNEL_HEIGHT(snla)); - ymax = 0.0f; - } - else { - ymin = 0.0f; - ymax = (float)(-ACHANNEL_HEIGHT(ac)); - } - - /* 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); - - /* filter data */ - 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 box select */ - for (ale = anim_data.first; ale; ale = ale->next) { - if (ac->datatype == ANIMCONT_NLA) - ymin = ymax - NLACHANNEL_STEP(snla); - else - ymin = ymax - ACHANNEL_STEP(ac); - - /* if channel is within border-select region, alter it */ - if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) { - /* set selection flags only */ - ANIM_channel_setting_set(ac, ale, ACHANNEL_SETTING_SELECT, selectmode); - - /* type specific actions */ - switch (ale->type) { - case ANIMTYPE_GROUP: - { - bActionGroup *agrp = (bActionGroup *)ale->data; - select_pchan_for_action_group(ac, agrp, ale); - /* always clear active flag after doing this */ - agrp->flag &= ~AGRP_ACTIVE; - break; - } - case ANIMTYPE_NLATRACK: - { - 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; - } - } - } - - /* set minimum extent to be the maximum of the next channel */ - ymax = ymin; - } - - /* cleanup */ - ANIM_animdata_freelist(&anim_data); + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + SpaceNla *snla = (SpaceNla *)ac->sl; + View2D *v2d = &ac->ar->v2d; + rctf rectf; + float ymin, ymax; + + /* set initial y extents */ + if (ac->datatype == ANIMCONT_NLA) { + ymin = (float)(-NLACHANNEL_HEIGHT(snla)); + ymax = 0.0f; + } + else { + ymin = 0.0f; + ymax = (float)(-ACHANNEL_HEIGHT(ac)); + } + + /* 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); + + /* filter data */ + 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 box select */ + for (ale = anim_data.first; ale; ale = ale->next) { + if (ac->datatype == ANIMCONT_NLA) + ymin = ymax - NLACHANNEL_STEP(snla); + else + ymin = ymax - ACHANNEL_STEP(ac); + + /* if channel is within border-select region, alter it */ + if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) { + /* set selection flags only */ + ANIM_channel_setting_set(ac, ale, ACHANNEL_SETTING_SELECT, selectmode); + + /* type specific actions */ + switch (ale->type) { + case ANIMTYPE_GROUP: { + bActionGroup *agrp = (bActionGroup *)ale->data; + select_pchan_for_action_group(ac, agrp, ale); + /* always clear active flag after doing this */ + agrp->flag &= ~AGRP_ACTIVE; + break; + } + case ANIMTYPE_NLATRACK: { + 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; + } + } + } + + /* set minimum extent to be the maximum of the next channel */ + ymax = ymin; + } + + /* cleanup */ + ANIM_animdata_freelist(&anim_data); } /* ------------------- */ static int animchannels_box_select_exec(bContext *C, wmOperator *op) { - bAnimContext ac; - rcti rect; - short selectmode = 0; - const bool select = !RNA_boolean_get(op->ptr, "deselect"); - const bool extend = RNA_boolean_get(op->ptr, "extend"); + bAnimContext ac; + rcti rect; + short selectmode = 0; + const bool select = !RNA_boolean_get(op->ptr, "deselect"); + const bool extend = RNA_boolean_get(op->ptr, "extend"); - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - /* get settings from operator */ - WM_operator_properties_border_to_rcti(op, &rect); + /* get settings from operator */ + WM_operator_properties_border_to_rcti(op, &rect); - if (!extend) { - ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, true, ACHANNEL_SETFLAG_CLEAR); - } + if (!extend) { + ANIM_deselect_anim_channels(&ac, ac.data, ac.datatype, true, ACHANNEL_SETFLAG_CLEAR); + } - if (select) { - selectmode = ACHANNEL_SETFLAG_ADD; - } - else { - selectmode = ACHANNEL_SETFLAG_CLEAR; - } + if (select) { + selectmode = ACHANNEL_SETFLAG_ADD; + } + else { + selectmode = ACHANNEL_SETFLAG_CLEAR; + } - /* apply box_select animation channels */ - box_select_anim_channels(&ac, &rect, selectmode); + /* apply box_select animation channels */ + box_select_anim_channels(&ac, &rect, selectmode); - /* send notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL); + /* send notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static void ANIM_OT_channels_select_box(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Box Select"; - ot->idname = "ANIM_OT_channels_select_box"; - ot->description = "Select all animation channels within the specified region"; + /* identifiers */ + ot->name = "Box Select"; + ot->idname = "ANIM_OT_channels_select_box"; + ot->description = "Select all animation channels within the specified region"; - /* api callbacks */ - ot->invoke = WM_gesture_box_invoke; - ot->exec = animchannels_box_select_exec; - ot->modal = WM_gesture_box_modal; - ot->cancel = WM_gesture_box_cancel; + /* api callbacks */ + ot->invoke = WM_gesture_box_invoke; + ot->exec = animchannels_box_select_exec; + ot->modal = WM_gesture_box_modal; + ot->cancel = WM_gesture_box_cancel; - ot->poll = animedit_poll_channels_nla_tweakmode_off; + ot->poll = animedit_poll_channels_nla_tweakmode_off; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* rna */ - WM_operator_properties_gesture_box_select(ot); + /* rna */ + WM_operator_properties_gesture_box_select(ot); } /* ******************* Rename Operator ***************************** */ @@ -2545,114 +2563,131 @@ static void ANIM_OT_channels_select_box(wmOperatorType *ot) static bool rename_anim_channels(bAnimContext *ac, int channel_index) { - ListBase anim_data = {NULL, NULL}; - const bAnimChannelType *acf; - bAnimListElem *ale; - int filter; - bool success = false; - - /* get the channel that was clicked on */ - /* filter channels */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* get channel from index */ - ale = BLI_findlink(&anim_data, channel_index); - if (ale == NULL) { - /* channel not found */ - if (G.debug & G_DEBUG) - printf("Error: animation channel (index = %d) not found in rename_anim_channels()\n", channel_index); - - ANIM_animdata_freelist(&anim_data); - return false; - } - - /* check that channel can be renamed */ - acf = ANIM_channel_get_typeinfo(ale); - if (acf && acf->name_prop) { - PointerRNA ptr; - PropertyRNA *prop; - - /* ok if we can get name property to edit from this channel */ - if (acf->name_prop(ale, &ptr, &prop)) { - /* actually showing the rename textfield is done on redraw, - * so here we just store the index of this channel in the - * dopesheet data, which will get utilized when drawing the - * channel... - * - * +1 factor is for backwards compat issues - */ - if (ac->ads) { - ac->ads->renameIndex = channel_index + 1; - success = true; - } - } - } - - /* free temp data and tag for refresh */ - ANIM_animdata_freelist(&anim_data); - ED_region_tag_redraw(ac->ar); - return success; + ListBase anim_data = {NULL, NULL}; + const bAnimChannelType *acf; + bAnimListElem *ale; + int filter; + bool success = false; + + /* get the channel that was clicked on */ + /* filter channels */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* get channel from index */ + ale = BLI_findlink(&anim_data, channel_index); + if (ale == NULL) { + /* channel not found */ + if (G.debug & G_DEBUG) + printf("Error: animation channel (index = %d) not found in rename_anim_channels()\n", + channel_index); + + ANIM_animdata_freelist(&anim_data); + return false; + } + + /* check that channel can be renamed */ + acf = ANIM_channel_get_typeinfo(ale); + if (acf && acf->name_prop) { + PointerRNA ptr; + PropertyRNA *prop; + + /* ok if we can get name property to edit from this channel */ + if (acf->name_prop(ale, &ptr, &prop)) { + /* actually showing the rename textfield is done on redraw, + * so here we just store the index of this channel in the + * dopesheet data, which will get utilized when drawing the + * channel... + * + * +1 factor is for backwards compat issues + */ + if (ac->ads) { + ac->ads->renameIndex = channel_index + 1; + success = true; + } + } + } + + /* free temp data and tag for refresh */ + ANIM_animdata_freelist(&anim_data); + ED_region_tag_redraw(ac->ar); + return success; } static int animchannels_channel_get(bAnimContext *ac, const int mval[2]) { - ARegion *ar; - View2D *v2d; - int channel_index; - float x, y; - - /* get useful pointers from animation context data */ - 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 - * so that the tops of channels get caught ok. Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use - * ACHANNEL_HEIGHT_HALF. - */ - UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y); - - if (ac->datatype == ANIMCONT_NLA) { - SpaceNla *snla = (SpaceNla *)ac->sl; - UI_view2d_listview_view_to_cell(v2d, NLACHANNEL_NAMEWIDTH, NLACHANNEL_STEP(snla), 0, (float)NLACHANNEL_HEIGHT_HALF(snla), x, y, NULL, &channel_index); - } - else { - UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP(ac), 0, (float)ACHANNEL_HEIGHT_HALF(ac), x, y, NULL, &channel_index); - } - - return channel_index; + ARegion *ar; + View2D *v2d; + int channel_index; + float x, y; + + /* get useful pointers from animation context data */ + 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 + * so that the tops of channels get caught ok. Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use + * ACHANNEL_HEIGHT_HALF. + */ + UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y); + + if (ac->datatype == ANIMCONT_NLA) { + SpaceNla *snla = (SpaceNla *)ac->sl; + UI_view2d_listview_view_to_cell(v2d, + NLACHANNEL_NAMEWIDTH, + NLACHANNEL_STEP(snla), + 0, + (float)NLACHANNEL_HEIGHT_HALF(snla), + x, + y, + NULL, + &channel_index); + } + else { + UI_view2d_listview_view_to_cell(v2d, + ACHANNEL_NAMEWIDTH, + ACHANNEL_STEP(ac), + 0, + (float)ACHANNEL_HEIGHT_HALF(ac), + x, + y, + NULL, + &channel_index); + } + + return channel_index; } static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { - bAnimContext ac; - int channel_index; + bAnimContext ac; + int channel_index; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; - channel_index = animchannels_channel_get(&ac, event->mval); + channel_index = animchannels_channel_get(&ac, event->mval); - /* handle click */ - if (rename_anim_channels(&ac, channel_index)) - return OPERATOR_FINISHED; - else - /* allow event to be handled by selectall operator */ - return OPERATOR_PASS_THROUGH; + /* handle click */ + if (rename_anim_channels(&ac, channel_index)) + return OPERATOR_FINISHED; + else + /* allow event to be handled by selectall operator */ + return OPERATOR_PASS_THROUGH; } static void ANIM_OT_channels_rename(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Rename Channels"; - ot->idname = "ANIM_OT_channels_rename"; - ot->description = "Rename animation channel under mouse"; + /* identifiers */ + 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; + /* api callbacks */ + ot->invoke = animchannels_rename_invoke; + ot->poll = animedit_poll_channels_active; } /* ******************** Mouse-Click Operator *********************** */ @@ -2660,357 +2695,355 @@ static void ANIM_OT_channels_rename(wmOperatorType *ot) static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index, short selectmode) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - int notifierFlags = 0; - - /* get the channel that was clicked on */ - /* filter channels */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* get channel from index */ - ale = BLI_findlink(&anim_data, channel_index); - if (ale == NULL) { - /* channel not found */ - if (G.debug & G_DEBUG) - printf("Error: animation channel (index = %d) not found in mouse_anim_channels()\n", channel_index); - - ANIM_animdata_freelist(&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? */ - if ((selectmode == -1) && (ale->type != ANIMTYPE_GROUP)) { - /* normal channels should not behave normally in this case */ - ANIM_animdata_freelist(&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 */ - switch (ale->type) { - case ANIMTYPE_SCENE: - { - Scene *sce = (Scene *)ale->data; - AnimData *adt = sce->adt; - - /* set selection status */ - if (selectmode == SELECT_INVERT) { - /* swap select */ - sce->flag ^= SCE_DS_SELECTED; - if (adt) adt->flag ^= ADT_UI_SELECTED; - } - else { - sce->flag |= SCE_DS_SELECTED; - if (adt) adt->flag |= ADT_UI_SELECTED; - } - - notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); - break; - } - case ANIMTYPE_OBJECT: - { + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + int notifierFlags = 0; + + /* get the channel that was clicked on */ + /* filter channels */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* get channel from index */ + ale = BLI_findlink(&anim_data, channel_index); + if (ale == NULL) { + /* channel not found */ + if (G.debug & G_DEBUG) + printf("Error: animation channel (index = %d) not found in mouse_anim_channels()\n", + channel_index); + + ANIM_animdata_freelist(&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? */ + if ((selectmode == -1) && (ale->type != ANIMTYPE_GROUP)) { + /* normal channels should not behave normally in this case */ + ANIM_animdata_freelist(&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 */ + switch (ale->type) { + case ANIMTYPE_SCENE: { + Scene *sce = (Scene *)ale->data; + AnimData *adt = sce->adt; + + /* set selection status */ + if (selectmode == SELECT_INVERT) { + /* swap select */ + sce->flag ^= SCE_DS_SELECTED; + if (adt) + adt->flag ^= ADT_UI_SELECTED; + } + else { + sce->flag |= SCE_DS_SELECTED; + if (adt) + adt->flag |= ADT_UI_SELECTED; + } + + notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); + break; + } + case ANIMTYPE_OBJECT: { #if 0 - bDopeSheet *ads = (bDopeSheet *)ac->data; - Scene *sce = (Scene *)ads->source; + bDopeSheet *ads = (bDopeSheet *)ac->data; + Scene *sce = (Scene *)ads->source; #endif - ViewLayer *view_layer = ac->view_layer; - Base *base = (Base *)ale->data; - Object *ob = base->object; - AnimData *adt = ob->adt; - - /* set selection status */ - if (base->flag & BASE_SELECTABLE) { - if (selectmode == SELECT_INVERT) { - /* swap select */ - ED_object_base_select(base, BA_INVERT); - BKE_scene_object_base_flag_sync_from_base(base); - - if (adt) adt->flag ^= ADT_UI_SELECTED; - } - else { - Base *b; - - /* deselect all */ - /* TODO: should this deselect all other types of channels too? */ - for (b = view_layer->object_bases.first; b; b = b->next) { - ED_object_base_select(b, BA_DESELECT); - BKE_scene_object_base_flag_sync_from_base(b); - if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE); - } - - /* select object now */ - ED_object_base_select(base, BA_SELECT); - BKE_scene_object_base_flag_sync_from_base(base); - if (adt) adt->flag |= ADT_UI_SELECTED; - } - - /* change active object - regardless of whether it is now selected [T37883] */ - ED_object_base_activate(C, base); /* adds notifier */ - - if ((adt) && (adt->flag & ADT_UI_SELECTED)) - adt->flag |= ADT_UI_ACTIVE; - - /* ensure we exit editmode on whatever object was active before to avoid getting stuck there - T48747 */ - if (ob != CTX_data_edit_object(C)) { - ED_object_editmode_exit(C, EM_FREEDATA); - } - - notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); - } - break; - } - case ANIMTYPE_FILLACTD: /* Action Expander */ - case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ - case ANIMTYPE_DSLAM: - case ANIMTYPE_DSCAM: - case ANIMTYPE_DSCACHEFILE: - case ANIMTYPE_DSCUR: - case ANIMTYPE_DSSKEY: - case ANIMTYPE_DSWOR: - case ANIMTYPE_DSPART: - case ANIMTYPE_DSMBALL: - case ANIMTYPE_DSARM: - case ANIMTYPE_DSMESH: - case ANIMTYPE_DSNTREE: - case ANIMTYPE_DSTEX: - case ANIMTYPE_DSLAT: - case ANIMTYPE_DSLINESTYLE: - case ANIMTYPE_DSSPK: - case ANIMTYPE_DSGPENCIL: - case ANIMTYPE_DSMCLIP: - { - /* sanity checking... */ - if (ale->adt) { - /* select/deselect */ - if (selectmode == SELECT_INVERT) { - /* inverse selection status of this AnimData block only */ - ale->adt->flag ^= ADT_UI_SELECTED; - } - else { - /* select AnimData block by itself */ - ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR); - ale->adt->flag |= ADT_UI_SELECTED; - } - - /* set active? */ - if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED)) - ale->adt->flag |= ADT_UI_ACTIVE; - } - - notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); - break; - } - case ANIMTYPE_GROUP: - { - bActionGroup *agrp = (bActionGroup *)ale->data; - - Object *ob = NULL; - bPoseChannel *pchan = NULL; - - - /* Armatures-Specific Feature: - * Since groups are used to collect F-Curves of the same Bone by default - * (via Keying Sets) so that they can be managed better, we try to make - * things here easier for animators by mapping group selection to bone - * selection. - * - * Only do this if "Only Selected" dopesheet filter is not active, or else it - * becomes too unpredictable/tricky to manage - */ - if ((ac->ads->filterflag & ADS_FILTER_ONLYSEL) == 0) { - if ((ale->id) && (GS(ale->id->name) == ID_OB)) { - ob = (Object *)ale->id; - - if (ob->type == OB_ARMATURE) { - /* Assume for now that any group with corresponding name is what we want - * (i.e. for an armature whose location is animated, things would break - * if the user were to add a bone named "Location"). - * - * TODO: check the first F-Curve or so to be sure... - */ - pchan = BKE_pose_channel_find_name(ob->pose, agrp->name); - } - } - } - - /* select/deselect group */ - if (selectmode == SELECT_INVERT) { - /* inverse selection status of this group only */ - agrp->flag ^= AGRP_SELECTED; - } - else if (selectmode == -1) { - /* select all in group (and deselect everything else) */ - FCurve *fcu; - - /* deselect all other channels */ - ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR); - if (pchan) ED_pose_deselect_all(ob, SEL_DESELECT, false); - - /* only select channels in group and group itself */ - for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcu->next) - fcu->flag |= FCURVE_SELECTED; - agrp->flag |= AGRP_SELECTED; - } - else { - /* select group by itself */ - ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR); - if (pchan) ED_pose_deselect_all(ob, SEL_DESELECT, false); - - agrp->flag |= AGRP_SELECTED; - } - - /* if group is selected now, make group the 'active' one in the visible list */ - if (agrp->flag & AGRP_SELECTED) { - ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP); - if (pchan) ED_pose_bone_select(ob, pchan, true); - } - else { - ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, NULL, ANIMTYPE_GROUP); - if (pchan) ED_pose_bone_select(ob, pchan, false); - } - - notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); - break; - } - case ANIMTYPE_FCURVE: - case ANIMTYPE_NLACURVE: - { - FCurve *fcu = (FCurve *)ale->data; - - /* select/deselect */ - if (selectmode == SELECT_INVERT) { - /* inverse selection status of this F-Curve only */ - fcu->flag ^= FCURVE_SELECTED; - } - else { - /* select F-Curve by itself */ - ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR); - fcu->flag |= FCURVE_SELECTED; - } - - /* if F-Curve is selected now, make F-Curve the 'active' one in the visible list */ - if (fcu->flag & FCURVE_SELECTED) - ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type); - - notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); - break; - } - case ANIMTYPE_SHAPEKEY: - { - KeyBlock *kb = (KeyBlock *)ale->data; - - /* select/deselect */ - if (selectmode == SELECT_INVERT) { - /* inverse selection status of this ShapeKey only */ - kb->flag ^= KEYBLOCK_SEL; - } - else { - /* select ShapeKey by itself */ - ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR); - kb->flag |= KEYBLOCK_SEL; - } - - notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); - break; - } - case ANIMTYPE_NLACONTROLS: - { - AnimData *adt = (AnimData *)ale->data; - - /* toggle expand - * - Although the triangle widget already allows this, since there's nothing else that can be done here now, - * let's just use it for easier expand/collapse for now - */ - adt->flag ^= ADT_NLA_SKEYS_COLLAPSED; - - notifierFlags |= (ND_ANIMCHAN | NA_EDITED); - break; - } - case ANIMTYPE_GPDATABLOCK: - { - bGPdata *gpd = (bGPdata *)ale->data; - - /* 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); - break; - } - case ANIMTYPE_GPLAYER: - { - bGPdata *gpd = (bGPdata *)ale->id; - bGPDlayer *gpl = (bGPDlayer *)ale->data; - - /* select/deselect */ - if (selectmode == SELECT_INVERT) { - /* invert selection status of this layer only */ - gpl->flag ^= GP_LAYER_SELECT; - } - else { - /* select layer by itself */ - ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR); - gpl->flag |= GP_LAYER_SELECT; - } - - /* change active layer, if this is selected (since we must always have an active layer) */ - if (gpl->flag & GP_LAYER_SELECT) { - ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, gpl, ANIMTYPE_GPLAYER); - /* update other layer status */ - BKE_gpencil_layer_setactive(gpd, gpl); - } - - /* Grease Pencil updates */ - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL); - notifierFlags |= (ND_ANIMCHAN | NA_EDITED); /* Animation Editors updates */ - 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, false, ACHANNEL_SETFLAG_CLEAR); - masklay->flag |= MASK_LAYERFLAG_SELECT; - } - - notifierFlags |= (ND_ANIMCHAN | NA_EDITED); - break; - } - default: - if (G.debug & G_DEBUG) - printf("Error: Invalid channel type in mouse_anim_channels()\n"); - break; - } - - /* free channels */ - ANIM_animdata_freelist(&anim_data); - - /* return notifier flags */ - return notifierFlags; + ViewLayer *view_layer = ac->view_layer; + Base *base = (Base *)ale->data; + Object *ob = base->object; + AnimData *adt = ob->adt; + + /* set selection status */ + if (base->flag & BASE_SELECTABLE) { + if (selectmode == SELECT_INVERT) { + /* swap select */ + ED_object_base_select(base, BA_INVERT); + BKE_scene_object_base_flag_sync_from_base(base); + + if (adt) + adt->flag ^= ADT_UI_SELECTED; + } + else { + Base *b; + + /* deselect all */ + /* TODO: should this deselect all other types of channels too? */ + for (b = view_layer->object_bases.first; b; b = b->next) { + ED_object_base_select(b, BA_DESELECT); + BKE_scene_object_base_flag_sync_from_base(b); + if (b->object->adt) + b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE); + } + + /* select object now */ + ED_object_base_select(base, BA_SELECT); + BKE_scene_object_base_flag_sync_from_base(base); + if (adt) + adt->flag |= ADT_UI_SELECTED; + } + + /* change active object - regardless of whether it is now selected [T37883] */ + ED_object_base_activate(C, base); /* adds notifier */ + + if ((adt) && (adt->flag & ADT_UI_SELECTED)) + adt->flag |= ADT_UI_ACTIVE; + + /* ensure we exit editmode on whatever object was active before to avoid getting stuck there - T48747 */ + if (ob != CTX_data_edit_object(C)) { + ED_object_editmode_exit(C, EM_FREEDATA); + } + + notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); + } + break; + } + case ANIMTYPE_FILLACTD: /* Action Expander */ + case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ + case ANIMTYPE_DSLAM: + case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCACHEFILE: + case ANIMTYPE_DSCUR: + case ANIMTYPE_DSSKEY: + case ANIMTYPE_DSWOR: + case ANIMTYPE_DSPART: + case ANIMTYPE_DSMBALL: + case ANIMTYPE_DSARM: + case ANIMTYPE_DSMESH: + case ANIMTYPE_DSNTREE: + case ANIMTYPE_DSTEX: + case ANIMTYPE_DSLAT: + case ANIMTYPE_DSLINESTYLE: + case ANIMTYPE_DSSPK: + case ANIMTYPE_DSGPENCIL: + case ANIMTYPE_DSMCLIP: { + /* sanity checking... */ + if (ale->adt) { + /* select/deselect */ + if (selectmode == SELECT_INVERT) { + /* inverse selection status of this AnimData block only */ + ale->adt->flag ^= ADT_UI_SELECTED; + } + else { + /* select AnimData block by itself */ + ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR); + ale->adt->flag |= ADT_UI_SELECTED; + } + + /* set active? */ + if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED)) + ale->adt->flag |= ADT_UI_ACTIVE; + } + + notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); + break; + } + case ANIMTYPE_GROUP: { + bActionGroup *agrp = (bActionGroup *)ale->data; + + Object *ob = NULL; + bPoseChannel *pchan = NULL; + + /* Armatures-Specific Feature: + * Since groups are used to collect F-Curves of the same Bone by default + * (via Keying Sets) so that they can be managed better, we try to make + * things here easier for animators by mapping group selection to bone + * selection. + * + * Only do this if "Only Selected" dopesheet filter is not active, or else it + * becomes too unpredictable/tricky to manage + */ + if ((ac->ads->filterflag & ADS_FILTER_ONLYSEL) == 0) { + if ((ale->id) && (GS(ale->id->name) == ID_OB)) { + ob = (Object *)ale->id; + + if (ob->type == OB_ARMATURE) { + /* Assume for now that any group with corresponding name is what we want + * (i.e. for an armature whose location is animated, things would break + * if the user were to add a bone named "Location"). + * + * TODO: check the first F-Curve or so to be sure... + */ + pchan = BKE_pose_channel_find_name(ob->pose, agrp->name); + } + } + } + + /* select/deselect group */ + if (selectmode == SELECT_INVERT) { + /* inverse selection status of this group only */ + agrp->flag ^= AGRP_SELECTED; + } + else if (selectmode == -1) { + /* select all in group (and deselect everything else) */ + FCurve *fcu; + + /* deselect all other channels */ + ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR); + if (pchan) + ED_pose_deselect_all(ob, SEL_DESELECT, false); + + /* only select channels in group and group itself */ + for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcu->next) + fcu->flag |= FCURVE_SELECTED; + agrp->flag |= AGRP_SELECTED; + } + else { + /* select group by itself */ + ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR); + if (pchan) + ED_pose_deselect_all(ob, SEL_DESELECT, false); + + agrp->flag |= AGRP_SELECTED; + } + + /* if group is selected now, make group the 'active' one in the visible list */ + if (agrp->flag & AGRP_SELECTED) { + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP); + if (pchan) + ED_pose_bone_select(ob, pchan, true); + } + else { + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, NULL, ANIMTYPE_GROUP); + if (pchan) + ED_pose_bone_select(ob, pchan, false); + } + + notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); + break; + } + case ANIMTYPE_FCURVE: + case ANIMTYPE_NLACURVE: { + FCurve *fcu = (FCurve *)ale->data; + + /* select/deselect */ + if (selectmode == SELECT_INVERT) { + /* inverse selection status of this F-Curve only */ + fcu->flag ^= FCURVE_SELECTED; + } + else { + /* select F-Curve by itself */ + ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR); + fcu->flag |= FCURVE_SELECTED; + } + + /* if F-Curve is selected now, make F-Curve the 'active' one in the visible list */ + if (fcu->flag & FCURVE_SELECTED) + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type); + + notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); + break; + } + case ANIMTYPE_SHAPEKEY: { + KeyBlock *kb = (KeyBlock *)ale->data; + + /* select/deselect */ + if (selectmode == SELECT_INVERT) { + /* inverse selection status of this ShapeKey only */ + kb->flag ^= KEYBLOCK_SEL; + } + else { + /* select ShapeKey by itself */ + ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR); + kb->flag |= KEYBLOCK_SEL; + } + + notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); + break; + } + case ANIMTYPE_NLACONTROLS: { + AnimData *adt = (AnimData *)ale->data; + + /* toggle expand + * - Although the triangle widget already allows this, since there's nothing else that can be done here now, + * let's just use it for easier expand/collapse for now + */ + adt->flag ^= ADT_NLA_SKEYS_COLLAPSED; + + notifierFlags |= (ND_ANIMCHAN | NA_EDITED); + break; + } + case ANIMTYPE_GPDATABLOCK: { + bGPdata *gpd = (bGPdata *)ale->data; + + /* 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); + break; + } + case ANIMTYPE_GPLAYER: { + bGPdata *gpd = (bGPdata *)ale->id; + bGPDlayer *gpl = (bGPDlayer *)ale->data; + + /* select/deselect */ + if (selectmode == SELECT_INVERT) { + /* invert selection status of this layer only */ + gpl->flag ^= GP_LAYER_SELECT; + } + else { + /* select layer by itself */ + ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR); + gpl->flag |= GP_LAYER_SELECT; + } + + /* change active layer, if this is selected (since we must always have an active layer) */ + if (gpl->flag & GP_LAYER_SELECT) { + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, gpl, ANIMTYPE_GPLAYER); + /* update other layer status */ + BKE_gpencil_layer_setactive(gpd, gpl); + } + + /* Grease Pencil updates */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL); + notifierFlags |= (ND_ANIMCHAN | NA_EDITED); /* Animation Editors updates */ + 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, false, ACHANNEL_SETFLAG_CLEAR); + masklay->flag |= MASK_LAYERFLAG_SELECT; + } + + notifierFlags |= (ND_ANIMCHAN | NA_EDITED); + break; + } + default: + if (G.debug & G_DEBUG) + printf("Error: Invalid channel type in mouse_anim_channels()\n"); + break; + } + + /* free channels */ + ANIM_animdata_freelist(&anim_data); + + /* return notifier flags */ + return notifierFlags; } /* ------------------- */ @@ -3018,177 +3051,188 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index, /* handle clicking */ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - bAnimContext ac; - ARegion *ar; - View2D *v2d; - int channel_index; - int notifierFlags = 0; - short selectmode; - float x, y; - - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* get useful pointers from animation context data */ - ar = ac.ar; - 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; - } - else if (RNA_boolean_get(op->ptr, "children_only")) { - /* this is a bit of a special case for ActionGroups only... - * should it be removed or extended to all instead? */ - selectmode = -1; - } - else { - 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 so that the tops of channels get caught ok. - * Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use ACHANNEL_HEIGHT_HALF. - */ - UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y); - UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP(&ac), 0, (float)ACHANNEL_HEIGHT_HALF(&ac), x, y, NULL, &channel_index); - - /* handle mouse-click in the relevant channel then */ - notifierFlags = mouse_anim_channels(C, &ac, channel_index, selectmode); - - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | notifierFlags, NULL); - - return OPERATOR_FINISHED; + bAnimContext ac; + ARegion *ar; + View2D *v2d; + int channel_index; + int notifierFlags = 0; + short selectmode; + float x, y; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get useful pointers from animation context data */ + ar = ac.ar; + 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; + } + else if (RNA_boolean_get(op->ptr, "children_only")) { + /* this is a bit of a special case for ActionGroups only... + * should it be removed or extended to all instead? */ + selectmode = -1; + } + else { + 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 so that the tops of channels get caught ok. + * Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use ACHANNEL_HEIGHT_HALF. + */ + UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y); + UI_view2d_listview_view_to_cell(v2d, + ACHANNEL_NAMEWIDTH, + ACHANNEL_STEP(&ac), + 0, + (float)ACHANNEL_HEIGHT_HALF(&ac), + x, + y, + NULL, + &channel_index); + + /* handle mouse-click in the relevant channel then */ + notifierFlags = mouse_anim_channels(C, &ac, channel_index, selectmode); + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | notifierFlags, NULL); + + return OPERATOR_FINISHED; } static void ANIM_OT_channels_click(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - /* identifiers */ - ot->name = "Mouse Click on Channels"; - ot->idname = "ANIM_OT_channels_click"; - ot->description = "Handle mouse-clicks over animation channels"; + /* identifiers */ + 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; + /* api callbacks */ + ot->invoke = animchannels_mouseclick_invoke; + ot->poll = animedit_poll_channels_active; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; - /* properties */ - /* NOTE: don't save settings, otherwise, can end up with some weird behavior (sticky extend) */ - prop = RNA_def_boolean(ot->srna, "extend", false, "Extend Select", ""); // SHIFTKEY - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + /* properties */ + /* NOTE: don't save settings, otherwise, can end up with some weird behavior (sticky extend) */ + prop = RNA_def_boolean(ot->srna, "extend", false, "Extend Select", ""); // SHIFTKEY + RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "children_only", false, "Select Children Only", ""); // CTRLKEY|SHIFTKEY - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, "children_only", false, "Select Children Only", ""); // CTRLKEY|SHIFTKEY + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } static bool select_anim_channel_keys(bAnimContext *ac, int channel_index, bool extend) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - bool success = false; - FCurve *fcu; - int i; - - /* get the channel that was clicked on */ - /* filter channels */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* get channel from index */ - ale = BLI_findlink(&anim_data, channel_index); - if (ale == NULL) { - /* channel not found */ - if (G.debug & G_DEBUG) - printf("Error: animation channel (index = %d) not found in rename_anim_channels()\n", channel_index); - - ANIM_animdata_freelist(&anim_data); - return false; - } - - fcu = (FCurve *)ale->key_data; - success = (fcu != NULL); - - ANIM_animdata_freelist(&anim_data); - - /* F-Curve may not have any keyframes */ - if (fcu && fcu->bezt) { - BezTriple *bezt; - - if (!extend) { - filter = (ANIMFILTER_DATA_VISIBLE); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu_inner = (FCurve *)ale->key_data; - - if (fcu_inner != NULL && fcu_inner->bezt != NULL) { - for (i = 0, bezt = fcu_inner->bezt; i < fcu_inner->totvert; i++, bezt++) { - bezt->f2 = bezt->f1 = bezt->f3 = 0; - } - } - } - - ANIM_animdata_freelist(&anim_data); - } - - for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { - bezt->f2 = bezt->f1 = bezt->f3 = SELECT; - } - } - - /* free temp data and tag for refresh */ - ED_region_tag_redraw(ac->ar); - return success; -} - -static int animchannels_channel_select_keys_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - bAnimContext ac; - int channel_index; - bool extend = RNA_boolean_get(op->ptr, "extend"); - - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - channel_index = animchannels_channel_get(&ac, event->mval); - - /* handle click */ - if (select_anim_channel_keys(&ac, channel_index, extend)) { - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); - return OPERATOR_FINISHED; - } - else - /* allow event to be handled by selectall operator */ - return OPERATOR_PASS_THROUGH; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + bool success = false; + FCurve *fcu; + int i; + + /* get the channel that was clicked on */ + /* filter channels */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* get channel from index */ + ale = BLI_findlink(&anim_data, channel_index); + if (ale == NULL) { + /* channel not found */ + if (G.debug & G_DEBUG) + printf("Error: animation channel (index = %d) not found in rename_anim_channels()\n", + channel_index); + + ANIM_animdata_freelist(&anim_data); + return false; + } + + fcu = (FCurve *)ale->key_data; + success = (fcu != NULL); + + ANIM_animdata_freelist(&anim_data); + + /* F-Curve may not have any keyframes */ + if (fcu && fcu->bezt) { + BezTriple *bezt; + + if (!extend) { + filter = (ANIMFILTER_DATA_VISIBLE); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu_inner = (FCurve *)ale->key_data; + + if (fcu_inner != NULL && fcu_inner->bezt != NULL) { + for (i = 0, bezt = fcu_inner->bezt; i < fcu_inner->totvert; i++, bezt++) { + bezt->f2 = bezt->f1 = bezt->f3 = 0; + } + } + } + + ANIM_animdata_freelist(&anim_data); + } + + for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { + bezt->f2 = bezt->f1 = bezt->f3 = SELECT; + } + } + + /* free temp data and tag for refresh */ + ED_region_tag_redraw(ac->ar); + return success; +} + +static int animchannels_channel_select_keys_invoke(bContext *C, + wmOperator *op, + const wmEvent *event) +{ + bAnimContext ac; + int channel_index; + bool extend = RNA_boolean_get(op->ptr, "extend"); + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + channel_index = animchannels_channel_get(&ac, event->mval); + + /* handle click */ + if (select_anim_channel_keys(&ac, channel_index, extend)) { + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); + return OPERATOR_FINISHED; + } + else + /* allow event to be handled by selectall operator */ + return OPERATOR_PASS_THROUGH; } static void ANIM_OT_channel_select_keys(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - /* identifiers */ - ot->name = "Select Channel keyframes"; - ot->idname = "ANIM_OT_channel_select_keys"; - ot->description = "Select all keyframes of channel under mouse"; + /* identifiers */ + ot->name = "Select Channel keyframes"; + ot->idname = "ANIM_OT_channel_select_keys"; + ot->description = "Select all keyframes of channel under mouse"; - /* api callbacks */ - ot->invoke = animchannels_channel_select_keys_invoke; - ot->poll = animedit_poll_channels_active; + /* api callbacks */ + ot->invoke = animchannels_channel_select_keys_invoke; + ot->poll = animedit_poll_channels_active; - prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* ************************************************************************** */ @@ -3196,41 +3240,41 @@ static void ANIM_OT_channel_select_keys(wmOperatorType *ot) void ED_operatortypes_animchannels(void) { - WM_operatortype_append(ANIM_OT_channels_select_all); - WM_operatortype_append(ANIM_OT_channels_select_box); + WM_operatortype_append(ANIM_OT_channels_select_all); + WM_operatortype_append(ANIM_OT_channels_select_box); - WM_operatortype_append(ANIM_OT_channels_click); - WM_operatortype_append(ANIM_OT_channel_select_keys); - WM_operatortype_append(ANIM_OT_channels_rename); + WM_operatortype_append(ANIM_OT_channels_click); + WM_operatortype_append(ANIM_OT_channel_select_keys); + WM_operatortype_append(ANIM_OT_channels_rename); - WM_operatortype_append(ANIM_OT_channels_find); + WM_operatortype_append(ANIM_OT_channels_find); - 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_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); + WM_operatortype_append(ANIM_OT_channels_delete); - /* XXX does this need to be a separate operator? */ - WM_operatortype_append(ANIM_OT_channels_editable_toggle); + /* XXX does this need to be a separate operator? */ + WM_operatortype_append(ANIM_OT_channels_editable_toggle); - WM_operatortype_append(ANIM_OT_channels_move); + WM_operatortype_append(ANIM_OT_channels_move); - WM_operatortype_append(ANIM_OT_channels_expand); - WM_operatortype_append(ANIM_OT_channels_collapse); + WM_operatortype_append(ANIM_OT_channels_expand); + WM_operatortype_append(ANIM_OT_channels_collapse); - WM_operatortype_append(ANIM_OT_channels_fcurves_enable); + WM_operatortype_append(ANIM_OT_channels_fcurves_enable); - WM_operatortype_append(ANIM_OT_channels_clean_empty); + WM_operatortype_append(ANIM_OT_channels_clean_empty); - WM_operatortype_append(ANIM_OT_channels_group); - WM_operatortype_append(ANIM_OT_channels_ungroup); + 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 void ED_keymap_animchannels(wmKeyConfig *keyconf) { - WM_keymap_ensure(keyconf, "Animation Channels", 0, 0); + WM_keymap_ensure(keyconf, "Animation Channels", 0, 0); } /* ************************************************************************** */ |