diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2015-03-30 11:50:59 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2015-03-30 11:50:59 +0300 |
commit | d7ddffdcce6db03e63c09c566b57a1252101058f (patch) | |
tree | ae967c1bafeaf6abbe76012772d49ea488076fe6 /source/blender/editors/animation | |
parent | a5180abde0b5b958b331c026d4cd1628b6d2c747 (diff) | |
parent | 59740a6c985efbf5369d27a5919e184036d0287a (diff) |
Merge branch 'master' into gooseberry
Conflicts:
release/scripts/startup/bl_ui/properties_physics_smoke.py
source/blender/editors/include/ED_transform.h
source/blender/editors/space_view3d/view3d_intern.h
Diffstat (limited to 'source/blender/editors/animation')
-rw-r--r-- | source/blender/editors/animation/anim_channels_defines.c | 219 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_channels_edit.c | 96 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_draw.c | 12 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_filter.c | 98 | ||||
-rw-r--r-- | source/blender/editors/animation/keyframing.c | 48 |
5 files changed, 436 insertions, 37 deletions
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 37c40052275..7eb32d4dc45 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -1017,6 +1017,149 @@ static bAnimChannelType ACF_FCURVE = acf_fcurve_setting_ptr /* pointer for setting */ }; +/* NLA Control FCurves Expander ----------------------- */ + +/* get backdrop color for nla controls widget */ +static void acf_nla_controls_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3]) +{ + // TODO: give this its own theme setting? + UI_GetThemeColorShade3fv(TH_GROUP, 55, r_color); +} + +/* backdrop for nla controls expander widget */ +static void acf_nla_controls_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) +{ + bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + View2D *v2d = &ac->ar->v2d; + short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0; + short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0; + float color[3]; + + /* set backdrop drawing color */ + acf->get_backdrop_color(ac, ale, color); + glColor3fv(color); + + /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */ + UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)); + UI_draw_roundbox_gl_mode(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5); +} + +/* name for nla controls expander entries */ +static void acf_nla_controls_name(bAnimListElem *UNUSED(ale), char *name) +{ + BLI_strncpy(name, IFACE_("NLA Strip Controls"), ANIM_CHAN_NAME_SIZE); +} + +/* check if some setting exists for this channel */ +static bool acf_nla_controls_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting) +{ + /* for now, all settings are supported, though some are only conditionally */ + switch (setting) { + /* supported */ + case ACHANNEL_SETTING_EXPAND: + return true; + + // TOOD: selected? + + default: /* unsupported */ + return false; + } +} + +/* get the appropriate flag(s) for the setting when it is valid */ +static int acf_nla_controls_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) +{ + /* clear extra return data first */ + *neg = false; + + switch (setting) { + case ACHANNEL_SETTING_EXPAND: /* expanded */ + *neg = true; + return ADT_NLA_SKEYS_COLLAPSED; + + default: + /* this shouldn't happen */ + return 0; + } +} + +/* get pointer to the setting */ +static void *acf_nla_controls_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type) +{ + AnimData *adt = (AnimData *)ale->data; + + /* all flags are just in adt->flag for now... */ + return GET_ACF_FLAG_PTR(adt->flag, type); +} + +static int acf_nla_controls_icon(bAnimListElem *UNUSED(ale)) +{ + return ICON_NLA; +} + +/* NLA Control FCurves Expander type define */ +static bAnimChannelType ACF_NLACONTROLS = +{ + "NLA Controls Expander", /* type name */ + ACHANNEL_ROLE_EXPANDER, /* role */ + + acf_nla_controls_color, /* backdrop color */ + acf_nla_controls_backdrop, /* backdrop */ + acf_generic_indention_0, /* indent level */ + acf_generic_group_offset, /* offset */ + + acf_nla_controls_name, /* name */ + NULL, /* name prop */ + acf_nla_controls_icon, /* icon */ + + acf_nla_controls_setting_valid, /* has setting */ + acf_nla_controls_setting_flag, /* flag for setting */ + acf_nla_controls_setting_ptr /* pointer for setting */ +}; + + +/* NLA Control F-Curve -------------------------------- */ + +/* name for nla control fcurve entries */ +static void acf_nla_curve_name(bAnimListElem *ale, char *name) +{ + NlaStrip *strip = ale->owner; + FCurve *fcu = ale->data; + PropertyRNA *prop; + + /* try to get RNA property that this shortened path (relative to the strip) refers to */ + prop = RNA_struct_type_find_property(&RNA_NlaStrip, fcu->rna_path); + if (prop) { + /* "name" of this strip displays the UI identifier + the name of the NlaStrip */ + BLI_snprintf(name, 256, "%s (%s)", RNA_property_ui_name(prop), strip->name); + } + else { + /* unknown property... */ + BLI_snprintf(name, 256, "%s[%d]", fcu->rna_path, fcu->array_index); + } +} + + +/* NLA Control F-Curve type define */ +static bAnimChannelType ACF_NLACURVE = +{ + "NLA Control F-Curve", /* type name */ + ACHANNEL_ROLE_CHANNEL, /* role */ + + acf_generic_channel_color, /* backdrop color */ + acf_generic_channel_backdrop, /* backdrop */ + acf_generic_indention_1, /* indent level */ + acf_generic_group_offset, /* offset */ + + acf_nla_curve_name, /* name */ + acf_fcurve_name_prop, /* name prop */ + NULL, /* icon */ + + acf_fcurve_setting_valid, /* has setting */ + acf_fcurve_setting_flag, /* flag for setting */ + acf_fcurve_setting_ptr /* pointer for setting */ +}; + /* Object Action Expander ------------------------------------------- */ // TODO: just get this from RNA? @@ -3222,6 +3365,9 @@ static void ANIM_init_channel_typeinfo_data(void) animchannelTypeInfo[type++] = &ACF_GROUP; /* Group */ animchannelTypeInfo[type++] = &ACF_FCURVE; /* F-Curve */ + animchannelTypeInfo[type++] = &ACF_NLACONTROLS; /* NLA Control FCurve Expander */ + animchannelTypeInfo[type++] = &ACF_NLACURVE; /* NLA Control FCurve Channel */ + animchannelTypeInfo[type++] = &ACF_FILLACTD; /* Object Action Expander */ animchannelTypeInfo[type++] = &ACF_FILLDRIVERS; /* Drivers Expander */ @@ -3491,7 +3637,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float if (ac->sl) { if ((ac->spacetype == SPACE_IPO) && acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) { /* for F-Curves, draw color-preview of curve behind checkbox */ - if (ale->type == ANIMTYPE_FCURVE) { + if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) { FCurve *fcu = (FCurve *)ale->data; /* F-Curve channels need to have a special 'color code' box drawn, which is colored with whatever @@ -3537,7 +3683,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float UI_fontstyle_draw_simple(fstyle, offset, ytext, name); /* draw red underline if channel is disabled */ - if ((ale->type == ANIMTYPE_FCURVE) && (ale->flag & FCURVE_DISABLED)) { + if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE) && (ale->flag & FCURVE_DISABLED)) { /* FIXME: replace hardcoded color here, and check on extents! */ glColor3f(1.0f, 0.0f, 0.0f); glLineWidth(2.0); @@ -3604,7 +3750,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float * (only only F-Curves really can support them for now) * - slider should start before the toggles (if they're visible) to keep a clean line down the side */ - if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_SHAPEKEY)) { + if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE, ANIMTYPE_SHAPEKEY)) { /* adjust offset */ offset += SLIDER_WIDTH; } @@ -3771,6 +3917,44 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi MEM_freeN(rna_path); } +/* callback for NLA Control Curve widget sliders - insert keyframes */ +static void achannel_setting_slider_nla_curve_cb(bContext *C, void *UNUSED(id_poin), void *fcu_poin) +{ + /* ID *id = (ID *)id_poin; */ + FCurve *fcu = (FCurve *)fcu_poin; + + PointerRNA ptr; + PropertyRNA *prop; + int index; + + ReportList *reports = CTX_wm_reports(C); + Scene *scene = CTX_data_scene(C); + short flag = 0; + bool done = false; + float cfra; + + /* get current frame - *no* NLA mapping should be done */ + cfra = (float)CFRA; + + /* get flags for keyframing */ + flag = ANIM_get_keyframing_flags(scene, 1); + + /* get pointer and property from the slider - this should all match up with the NlaStrip required... */ + UI_context_active_but_prop_get(C, &ptr, &prop, &index); + + if (fcu && prop) { + /* set the special 'replace' flag if on a keyframe */ + if (fcurve_frame_has_keyframe(fcu, cfra, 0)) + flag |= INSERTKEY_REPLACE; + + /* insert a keyframe for this F-Curve */ + done = insert_keyframe_direct(reports, ptr, prop, fcu, cfra, flag); + + if (done) + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + } +} + /* Draw a widget for some setting */ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChannelType *acf, uiBlock *block, int xpos, int ypos, int setting) @@ -3793,7 +3977,7 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChann //icon = ((enabled) ? ICON_VISIBLE_IPO_ON : ICON_VISIBLE_IPO_OFF); icon = ICON_VISIBLE_IPO_OFF; - if (ale->type == ANIMTYPE_FCURVE) + if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) tooltip = TIP_("F-Curve is visible in Graph Editor for editing"); else tooltip = TIP_("Channels are visible in Graph Editor for editing"); @@ -3828,7 +4012,7 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChann //icon = ((enabled) ? ICON_MUTE_IPO_ON : ICON_MUTE_IPO_OFF); icon = ICON_MUTE_IPO_OFF; - if (ale->type == ANIMTYPE_FCURVE) { + if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) { tooltip = TIP_("Does F-Curve contribute to result"); } else if ((ac) && (ac->spacetype == SPACE_NLA) && (ale->type != ANIMTYPE_NLATRACK)) { @@ -4097,7 +4281,7 @@ void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListEle * and wouldn't be able to auto-keyframe... * - slider should start before the toggles (if they're visible) to keep a clean line down the side */ - if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_SHAPEKEY)) { + if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE, ANIMTYPE_SHAPEKEY)) { /* adjust offset */ // TODO: make slider width dynamic, so that they can be easier to use when the view is wide enough offset += SLIDER_WIDTH; @@ -4105,7 +4289,28 @@ void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListEle /* need backdrop behind sliders... */ UI_block_emboss_set(block, UI_EMBOSS); - if (ale->id) { /* Slider using RNA Access -------------------- */ + if (ale->owner) { /* Slider using custom RNA Access ---------- */ + if (ale->type == ANIMTYPE_NLACURVE) { + NlaStrip *strip = (NlaStrip *)ale->owner; + FCurve *fcu = (FCurve *)ale->data; + PointerRNA ptr; + PropertyRNA *prop; + + /* create RNA pointers */ + RNA_pointer_create(ale->id, &RNA_NlaStrip, strip, &ptr); + prop = RNA_struct_find_property(&ptr, fcu->rna_path); + + /* create property slider */ + if (prop) { + uiBut *but; + + /* create the slider button, and assign relevant callback to ensure keyframes are inserted... */ + but = uiDefAutoButR(block, &ptr, prop, fcu->array_index, "", ICON_NONE, (int)v2d->cur.xmax - offset, ymid, SLIDER_WIDTH, (int)ymaxc - yminc); + UI_but_func_set(but, achannel_setting_slider_nla_curve_cb, ale->id, ale->data); + } + } + } + else if (ale->id) { /* Slider using RNA Access --------------- */ PointerRNA id_ptr, ptr; PropertyRNA *prop; char *rna_path = NULL; diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index d8ad6506186..cf2fa9fffe1 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -101,6 +101,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 +158,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 +257,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 +342,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; @@ -847,6 +851,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 +1196,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 +1317,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 +1657,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 */ @@ -2727,7 +2803,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 +2821,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 +2844,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; diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 0e052279796..c0ac42f3a5d 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -173,10 +173,14 @@ AnimData *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale) if (G.is_rendering) return NULL; /* handling depends on the type of animation-context we've got */ - if (ale) - return ale->adt; - else - return NULL; + if (ale) { + /* NLA Control Curves occur on NLA strips, and shouldn't be subjected to this kind of mapping */ + if (ale->type != ANIMTYPE_NLACURVE) + return ale->adt; + } + + /* cannot handle... */ + return NULL; } /* ------------------- */ diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 09c8af8c1b4..2f8d002fa48 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -424,6 +424,7 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac) * - adtOk: line or block of code to execute for AnimData-blocks case (usually ANIMDATA_ADD_ANIMDATA) * - nlaOk: line or block of code to execute for NLA tracks+strips case * - driversOk: line or block of code to execute for Drivers case + * - nlaKeysOk: line or block of code for NLA Strip Keyframes case * - keysOk: line or block of code for Keyframes case * * The checks for the various cases are as follows: @@ -434,9 +435,10 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac) * converted to a new NLA strip, and the filtering options allow this * 2C) allow non-animated datablocks to be included so that datablocks can be added * 3) drivers: include drivers from animdata block (for Drivers mode in Graph Editor) - * 4) normal keyframes: only when there is an active action + * 4A) nla strip keyframes: these are the per-strip controls for time and influence + * 4B) normal keyframes: only when there is an active action */ -#define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, keysOk) \ +#define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, nlaKeysOk, keysOk) \ { \ if ((id)->adt) { \ if (!(filter_mode & ANIMFILTER_CURVE_VISIBLE) || !((id)->adt->flag & ADT_CURVES_NOT_VISIBLE)) { \ @@ -457,6 +459,9 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac) } \ } \ else { \ + if (ANIMDATA_HAS_NLA(id)) { \ + nlaKeysOk \ + } \ if (ANIMDATA_HAS_KEYS(id)) { \ keysOk \ } \ @@ -787,6 +792,16 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne ale->adt = BKE_animdata_from_id(data); break; } + case ANIMTYPE_NLACONTROLS: + { + AnimData *adt = (AnimData *)data; + + ale->flag = adt->flag; + + ale->key_data = NULL; + ale->datatype = ALE_NONE; + break; + } case ANIMTYPE_GROUP: { bActionGroup *agrp = (bActionGroup *)data; @@ -1306,6 +1321,80 @@ static size_t animfilter_nla(bAnimContext *UNUSED(ac), ListBase *anim_data, bDop return items; } +/* Include the control FCurves per NLA Strip in the channel list + * NOTE: This is includes the expander too... + */ +static size_t animfilter_nla_controls(ListBase *anim_data, bDopeSheet *ads, AnimData *adt, int filter_mode, ID *owner_id) +{ + ListBase tmp_data = {NULL, NULL}; + size_t tmp_items = 0; + size_t items = 0; + + /* add control curves from each NLA strip... */ + /* NOTE: ANIMTYPE_FCURVES are created here, to avoid duplicating the code needed */ + BEGIN_ANIMFILTER_SUBCHANNELS(((adt->flag & ADT_NLA_SKEYS_COLLAPSED) == 0)) + { + NlaTrack *nlt; + NlaStrip *strip; + + /* for now, we only go one level deep - so controls on grouped FCurves are not handled */ + for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { + for (strip = nlt->strips.first; strip; strip = strip->next) { + ListBase strip_curves = {NULL, NULL}; + size_t strip_items = 0; + + /* create the raw items */ + strip_items += animfilter_fcurves(&strip_curves, ads, strip->fcurves.first, NULL, filter_mode, owner_id); + + /* change their types and add extra data + * - There is no point making a separate copy of animfilter_fcurves for this now/yet, + * unless we later get per-element control curves for other stuff too + */ + if (strip_items) { + bAnimListElem *ale, *ale_n = NULL; + + for (ale = strip_curves.first; ale; ale = ale_n) { + ale_n = ale->next; + + /* change the type to being a FCurve for editing NLA strip controls */ + BLI_assert(ale->type == ANIMTYPE_FCURVE); + + ale->type = ANIMTYPE_NLACURVE; + ale->owner = strip; + + ale->adt = NULL; /* XXX: This way, there are no problems with time mapping errors */ + } + } + + /* add strip curves to the set of channels inside the group being collected */ + BLI_movelisttolist(&tmp_data, &strip_curves); + BLI_assert(BLI_listbase_is_empty(&strip_curves)); + tmp_items += strip_items; + } + } + } + END_ANIMFILTER_SUBCHANNELS; + + /* did we find anything? */ + if (tmp_items) { + /* add the expander as a channel first */ + if (filter_mode & ANIMFILTER_LIST_CHANNELS) { + /* currently these channels cannot be selected, so they should be skipped */ + if ((filter_mode & (ANIMFILTER_SEL | ANIMFILTER_UNSEL)) == 0) { + ANIMCHANNEL_NEW_CHANNEL(adt, ANIMTYPE_NLACONTROLS, owner_id); + } + } + + /* now add the list of collected channels */ + BLI_movelisttolist(anim_data, &tmp_data); + BLI_assert(BLI_listbase_is_empty(&tmp_data)); + items += tmp_items; + } + + /* return the numebr of items added ot the list */ + return items; +} + /* determine what animation data from AnimData block should get displayed */ static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *id, int filter_mode) { @@ -1333,6 +1422,9 @@ static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDope { /* Drivers */ items += animfilter_fcurves(anim_data, ads, adt->drivers.first, NULL, filter_mode, id); }, + { /* NLA Control Keyframes */ + items += animfilter_nla_controls(anim_data, ads, adt, filter_mode, id); + }, { /* Keyframes */ items += animfilter_action(ac, anim_data, ads, adt->action, filter_mode, id); } @@ -2215,6 +2307,7 @@ static size_t animdata_filter_ds_obanim(bAnimContext *ac, ListBase *anim_data, b cdata = adt; expanded = EXPANDED_DRVD(adt); }, + { /* NLA Strip Controls - no dedicated channel for now (XXX) */ }, { /* Keyframes */ type = ANIMTYPE_FILLACTD; cdata = adt->action; @@ -2392,6 +2485,7 @@ static size_t animdata_filter_ds_scene(bAnimContext *ac, ListBase *anim_data, bD cdata = adt; expanded = EXPANDED_DRVD(adt); }, + { /* NLA Strip Controls - no dedicated channel for now (XXX) */ }, { /* Keyframes */ type = ANIMTYPE_FILLACTD; cdata = adt->action; diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 7e2ce4cd3f1..68ef704272d 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -1707,33 +1707,39 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) UI_context_active_but_prop_get(C, &ptr, &prop, &index); if ((ptr.id.data && ptr.data && prop) && RNA_property_animateable(&ptr, prop)) { - path = RNA_path_from_ID_to_property(&ptr, prop); - - if (path) { - if (all) { - length = RNA_property_array_length(&ptr, prop); - - if (length) index = 0; - else length = 1; - } - else - length = 1; - - for (a = 0; a < length; a++) - success += insert_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, cfra, flag); - - MEM_freeN(path); - } - else if (ptr.type == &RNA_NlaStrip) { - /* handle special vars for NLA-strips */ + if (ptr.type == &RNA_NlaStrip) { + /* Handle special properties for NLA Strips, whose F-Curves are stored on the + * strips themselves. These are stored separately or else the properties will + * not have any effect. + */ NlaStrip *strip = (NlaStrip *)ptr.data; FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), flag); success += insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, 0); } else { - BKE_report(op->reports, RPT_WARNING, - "Failed to resolve path to property, try manually specifying this using a Keying Set instead"); + /* standard properties */ + path = RNA_path_from_ID_to_property(&ptr, prop); + + if (path) { + if (all) { + length = RNA_property_array_length(&ptr, prop); + + if (length) index = 0; + else length = 1; + } + else + length = 1; + + for (a = 0; a < length; a++) + success += insert_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, cfra, flag); + + MEM_freeN(path); + } + else { + BKE_report(op->reports, RPT_WARNING, + "Failed to resolve path to property, try manually specifying this using a Keying Set instead"); + } } } else { |