diff options
Diffstat (limited to 'source/blender/editors/animation/anim_channels_edit.c')
-rw-r--r-- | source/blender/editors/animation/anim_channels_edit.c | 262 |
1 files changed, 235 insertions, 27 deletions
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index d8ad6506186..d08a32c6e6b 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -34,6 +34,7 @@ #include "MEM_guardedalloc.h" +#include "BKE_depsgraph.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" #include "BLI_listbase.h" @@ -101,6 +102,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat break; } case ANIMTYPE_FCURVE: + case ANIMTYPE_NLACURVE: { FCurve *fcu = (FCurve *)ale->data; @@ -157,6 +159,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat break; } case ANIMTYPE_FCURVE: + case ANIMTYPE_NLACURVE: { FCurve *fcu = (FCurve *)channel_data; fcu->flag |= FCURVE_ACTIVE; @@ -255,6 +258,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d sel = ACHANNEL_SETFLAG_CLEAR; break; case ANIMTYPE_FCURVE: + case ANIMTYPE_NLACURVE: if (ale->flag & FCURVE_SELECTED) sel = ACHANNEL_SETFLAG_CLEAR; break; @@ -339,6 +343,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d break; } case ANIMTYPE_FCURVE: + case ANIMTYPE_NLACURVE: { FCurve *fcu = (FCurve *)ale->data; @@ -444,7 +449,7 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn return; } else { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale_setting); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale_setting); if (acf == NULL) { printf("ERROR: no channel info for the changed channel\n"); @@ -473,7 +478,7 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn { /* go backwards in the list, until the highest-ranking element (by indention has been covered) */ for (ale = match->prev; ale; ale = ale->prev) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); int level; /* if no channel info was found, skip, since this type might not have any useful info */ @@ -517,7 +522,7 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn { /* go forwards in the list, until the lowest-ranking element (by indention has been covered) */ for (ale = match->next; ale; ale = ale->next) { - bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); int level; /* if no channel info was found, skip, since this type might not have any useful info */ @@ -847,6 +852,7 @@ static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *sr break; } case ANIMTYPE_FCURVE: + case ANIMTYPE_NLACURVE: { FCurve *fcu = (FCurve *)channel; @@ -1191,6 +1197,40 @@ static void rearrange_action_channels(bAnimContext *ac, bAction *act, eRearrange /* ------------------- */ +static void rearrange_nla_control_channels(bAnimContext *ac, AnimData *adt, eRearrangeAnimChan_Mode mode) +{ + ListBase anim_data_visible = {NULL, NULL}; + + NlaTrack *nlt; + NlaStrip *strip; + + /* get rearranging function */ + AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode); + + if (rearrange_func == NULL) + return; + + /* skip if these curves aren't being shown */ + if (adt->flag & ADT_NLA_SKEYS_COLLAPSED) + return; + + /* Filter visible data. */ + rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_NLACURVE); + + /* we cannot rearrange between strips, but within each strip, we can rearrange those curves */ + for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { + for (strip = nlt->strips.first; strip; strip = strip->next) { + rearrange_animchannel_islands(&strip->fcurves, rearrange_func, mode, ANIMTYPE_NLACURVE, + &anim_data_visible); + } + } + + /* free temp data */ + BLI_freelistN(&anim_data_visible); +} + +/* ------------------- */ + static void rearrange_gpencil_channels(bAnimContext *ac, eRearrangeAnimChan_Mode mode) { ListBase anim_data = {NULL, NULL}; @@ -1278,13 +1318,29 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op) rearrange_driver_channels(&ac, adt, mode); break; + case ANIMCONT_ACTION: /* Single Action only... */ case ANIMCONT_SHAPEKEY: // DOUBLE CHECK ME... - default: /* some collection of actions */ + { 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; + } } } @@ -1602,6 +1658,27 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op)) ANIM_fcurve_delete_from_animdata(&ac, adt, fcu); break; } + case ANIMTYPE_NLACURVE: + { + /* NLA Control Curve - Deleting it should disable the corresponding setting... */ + NlaStrip *strip = (NlaStrip *)ale->owner; + FCurve *fcu = (FCurve *)ale->data; + + if (STREQ(fcu->rna_path, "strip_time")) { + strip->flag &= ~NLASTRIP_FLAG_USR_TIME; + } + else if (STREQ(fcu->rna_path, "influence")) { + strip->flag &= ~NLASTRIP_FLAG_USR_INFLUENCE; + } + else { + printf("ERROR: Trying to delete NLA Control Curve for unknown property '%s'\n", fcu->rna_path); + } + + /* unlink and free the F-Curve */ + BLI_remlink(&strip->fcurves, fcu); + free_fcurve(fcu); + break; + } case ANIMTYPE_GPLAYER: { /* Grease Pencil layer */ @@ -1631,7 +1708,8 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op)) /* send notifier that things have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + DAG_relations_tag_update(CTX_data_main(C)); + return OPERATOR_FINISHED; } @@ -2041,7 +2119,7 @@ static int animchannels_clean_empty_exec(bContext *C, wmOperator *UNUSED(op)) /* remove AnimData? */ if (action_empty && nla_empty && drivers_empty) { - BKE_free_animdata(id); + BKE_animdata_free(id); } } @@ -2420,12 +2498,13 @@ static void ANIM_OT_channels_select_border(wmOperatorType *ot) /* ******************* Rename Operator ***************************** */ /* Allow renaming some channels by clicking on them */ -static void rename_anim_channels(bAnimContext *ac, int channel_index) +static bool rename_anim_channels(bAnimContext *ac, int channel_index) { ListBase anim_data = {NULL, NULL}; - bAnimChannelType *acf; + const bAnimChannelType *acf; bAnimListElem *ale; int filter; + bool success = false; /* get the channel that was clicked on */ /* filter channels */ @@ -2440,7 +2519,7 @@ static void rename_anim_channels(bAnimContext *ac, int channel_index) printf("Error: animation channel (index = %d) not found in rename_anim_channels()\n", channel_index); ANIM_animdata_freelist(&anim_data); - return; + return false; } /* check that channel can be renamed */ @@ -2460,6 +2539,7 @@ static void rename_anim_channels(bAnimContext *ac, int channel_index) */ if (ac->ads) { ac->ads->renameIndex = channel_index + 1; + success = true; } } } @@ -2467,22 +2547,18 @@ static void rename_anim_channels(bAnimContext *ac, int channel_index) /* free temp data and tag for refresh */ ANIM_animdata_freelist(&anim_data); ED_region_tag_redraw(ac->ar); + return success; } -static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +static int animchannels_channel_get(bAnimContext *ac, const int mval[2]) { - bAnimContext ac; ARegion *ar; View2D *v2d; int channel_index; float x, y; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - /* get useful pointers from animation context data */ - ar = ac.ar; + ar = ac->ar; v2d = &ar->v2d; /* figure out which channel user clicked in @@ -2490,20 +2566,36 @@ static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const * so that the tops of channels get caught ok. Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use * ACHANNEL_HEIGHT_HALF. */ - UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y); + UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y); - if (ac.datatype == ANIMCONT_NLA) { - SpaceNla *snla = (SpaceNla *)ac.sl; + if (ac->datatype == ANIMCONT_NLA) { + SpaceNla *snla = (SpaceNla *)ac->sl; UI_view2d_listview_view_to_cell(v2d, NLACHANNEL_NAMEWIDTH, NLACHANNEL_STEP(snla), 0, (float)NLACHANNEL_HEIGHT_HALF(snla), x, y, NULL, &channel_index); } else { UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP, 0, (float)ACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index); } - + + return channel_index; +} + +static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +{ + bAnimContext ac; + int channel_index; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + channel_index = animchannels_channel_get(&ac, event->mval); + /* handle click */ - rename_anim_channels(&ac, channel_index); - - return OPERATOR_FINISHED; + if (rename_anim_channels(&ac, channel_index)) + return OPERATOR_FINISHED; + else + /* allow event to be handled by selectall operator */ + return OPERATOR_PASS_THROUGH; } static void ANIM_OT_channels_rename(wmOperatorType *ot) @@ -2727,7 +2819,8 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index, notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); break; } - case ANIMTYPE_FCURVE: + case ANIMTYPE_FCURVE: + case ANIMTYPE_NLACURVE: { FCurve *fcu = (FCurve *)ale->data; @@ -2744,7 +2837,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index, /* if F-Curve is selected now, make F-Curve the 'active' one in the visible list */ if (fcu->flag & FCURVE_SELECTED) - ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE); + ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type); notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); break; @@ -2767,6 +2860,19 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index, 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; @@ -2918,6 +3024,105 @@ static void ANIM_OT_channels_click(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } +static bool select_anim_channel_keys(bAnimContext *ac, int channel_index, bool extend) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + bool success = false; + FCurve *fcu; + int i; + + /* get the channel that was clicked on */ + /* filter channels */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* get channel from index */ + ale = BLI_findlink(&anim_data, channel_index); + if (ale == NULL) { + /* channel not found */ + if (G.debug & G_DEBUG) + printf("Error: animation channel (index = %d) not found in rename_anim_channels()\n", channel_index); + + ANIM_animdata_freelist(&anim_data); + return false; + } + + fcu = (FCurve *)ale->key_data; + success = (fcu != NULL); + + ANIM_animdata_freelist(&anim_data); + + /* F-Curve may not have any keyframes */ + if (fcu && fcu->bezt) { + BezTriple *bezt; + + if (!extend) { + filter = (ANIMFILTER_DATA_VISIBLE); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu_inner = (FCurve *)ale->key_data; + + if (fcu_inner) { + for (i = 0, bezt = fcu_inner->bezt; i < fcu_inner->totvert; i++, bezt++) { + bezt->f2 = bezt->f1 = bezt->f3 = 0; + } + } + } + + ANIM_animdata_freelist(&anim_data); + } + + for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { + bezt->f2 = bezt->f1 = bezt->f3 = SELECT; + } + } + + /* free temp data and tag for refresh */ + ED_region_tag_redraw(ac->ar); + return success; +} + +static int animchannels_channel_select_keys_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + bAnimContext ac; + int channel_index; + bool extend = RNA_boolean_get(op->ptr, "extend"); + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + channel_index = animchannels_channel_get(&ac, event->mval); + + /* handle click */ + if (select_anim_channel_keys(&ac, channel_index, extend)) { + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); + return OPERATOR_FINISHED; + } + else + /* allow event to be handled by selectall operator */ + return OPERATOR_PASS_THROUGH; +} + +static void ANIM_OT_channel_select_keys(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Select Channel keyframes"; + ot->idname = "ANIM_OT_channel_select_keys"; + ot->description = "Select all keyframes of channel under mouse"; + + /* api callbacks */ + ot->invoke = animchannels_channel_select_keys_invoke; + ot->poll = animedit_poll_channels_active; + + prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); +} + /* ************************************************************************** */ /* Operator Registration */ @@ -2927,8 +3132,9 @@ void ED_operatortypes_animchannels(void) WM_operatortype_append(ANIM_OT_channels_select_border); WM_operatortype_append(ANIM_OT_channels_click); + WM_operatortype_append(ANIM_OT_channel_select_keys); WM_operatortype_append(ANIM_OT_channels_rename); - + WM_operatortype_append(ANIM_OT_channels_find); WM_operatortype_append(ANIM_OT_channels_setting_enable); @@ -2968,7 +3174,9 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf) /* rename */ WM_keymap_add_item(keymap, "ANIM_OT_channels_rename", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "ANIM_OT_channels_rename", LEFTMOUSE, KM_DBL_CLICK, 0, 0); - + WM_keymap_add_item(keymap, "ANIM_OT_channel_select_keys", LEFTMOUSE, KM_DBL_CLICK, 0, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channel_select_keys", LEFTMOUSE, KM_DBL_CLICK, KM_SHIFT, 0)->ptr, "extend", true); + /* find (i.e. a shortcut for setting the name filter) */ WM_keymap_add_item(keymap, "ANIM_OT_channels_find", FKEY, KM_PRESS, KM_CTRL, 0); |