diff options
7 files changed, 186 insertions, 100 deletions
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 11d68ed6f75..72aa0c18cb3 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -908,6 +908,115 @@ static bAnimChannelType ACF_GROUP = acf_group_setting_ptr /* pointer for setting */ }; +/* F-Curve ------------------------------------------- */ + +/* name for fcurve entries */ +static void acf_fcurve_name(bAnimListElem *ale, char *name) +{ + getname_anim_fcurve(name, ale->id, ale->data); +} + +/* "name" property for fcurve entries */ +static bool acf_fcurve_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop) +{ + FCurve *fcu = (FCurve *)ale->data; + + /* Ctrl-Click Usability Convenience Hack: + * For disabled F-Curves, allow access to the RNA Path + * as our "name" so that user can perform quick fixes + */ + if (fcu->flag & FCURVE_DISABLED) { + RNA_pointer_create(ale->id, &RNA_FCurve, ale->data, ptr); + *prop = RNA_struct_find_property(ptr, "data_path"); + } + else { + /* for "normal" F-Curves - no editable name, but *prop may not be set properly yet... */ + *prop = NULL; + } + + return (*prop != NULL); +} + +/* check if some setting exists for this channel */ +static bool acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting) +{ + FCurve *fcu = (FCurve *)ale->data; + + switch (setting) { + /* unsupported */ + case ACHANNEL_SETTING_SOLO: /* Solo Flag is only for NLA */ + case ACHANNEL_SETTING_EXPAND: /* F-Curves are not containers */ + return false; + + /* conditionally available */ + case ACHANNEL_SETTING_PROTECT: /* Protection is only valid when there's keyframes */ + if (fcu->bezt) + return true; + else + return false; // NOTE: in this special case, we need to draw ICON_ZOOMOUT + + case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */ + return (ac->spacetype == SPACE_IPO); + + /* always available */ + default: + return true; + } +} + +/* get the appropriate flag(s) for the setting when it is valid */ +static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) +{ + /* clear extra return data first */ + *neg = false; + + switch (setting) { + case ACHANNEL_SETTING_SELECT: /* selected */ + return FCURVE_SELECTED; + + case ACHANNEL_SETTING_MUTE: /* muted */ + return FCURVE_MUTED; + + case ACHANNEL_SETTING_PROTECT: /* protected */ + return FCURVE_PROTECTED; + + case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */ + return FCURVE_VISIBLE; + + default: /* unsupported */ + return 0; + } +} + +/* get pointer to the setting */ +static void *acf_fcurve_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type) +{ + FCurve *fcu = (FCurve *)ale->data; + + /* all flags are just in agrp->flag for now... */ + return GET_ACF_FLAG_PTR(fcu->flag, type); +} + +/* fcurve type define */ +static bAnimChannelType ACF_FCURVE = +{ + "F-Curve", /* type name */ + ACHANNEL_ROLE_CHANNEL, /* role */ + + acf_generic_channel_color, /* backdrop color */ + acf_generic_channel_backdrop, /* backdrop */ + acf_generic_indention_flexible, /* indent level */ // xxx rename this to f-curves only? + acf_generic_group_offset, /* offset */ + + acf_fcurve_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 */ +}; + /* NLA Control FCurves Expander ----------------------- */ /* get backdrop color for nla controls widget */ @@ -1008,107 +1117,41 @@ static bAnimChannelType ACF_NLACONTROLS = acf_nla_controls_setting_ptr /* pointer for setting */ }; -/* F-Curve ------------------------------------------- */ -/* name for fcurve entries */ -static void acf_fcurve_name(bAnimListElem *ale, char *name) -{ - getname_anim_fcurve(name, ale->id, ale->data); -} +/* NLA Control F-Curve -------------------------------- */ -/* "name" property for fcurve entries */ -static bool acf_fcurve_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop) +/* name for nla control fcurve entries */ +static void acf_nla_curve_name(bAnimListElem *ale, char *name) { - FCurve *fcu = (FCurve *)ale->data; + NlaStrip *strip = ale->owner; + FCurve *fcu = ale->data; + PropertyRNA *prop; - /* Ctrl-Click Usability Convenience Hack: - * For disabled F-Curves, allow access to the RNA Path - * as our "name" so that user can perform quick fixes - */ - if (fcu->flag & FCURVE_DISABLED) { - RNA_pointer_create(ale->id, &RNA_FCurve, ale->data, ptr); - *prop = RNA_struct_find_property(ptr, "data_path"); + /* 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 { - /* for "normal" F-Curves - no editable name, but *prop may not be set properly yet... */ - *prop = NULL; - } - - return (*prop != NULL); -} - -/* check if some setting exists for this channel */ -static bool acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting) -{ - FCurve *fcu = (FCurve *)ale->data; - - switch (setting) { - /* unsupported */ - case ACHANNEL_SETTING_SOLO: /* Solo Flag is only for NLA */ - case ACHANNEL_SETTING_EXPAND: /* F-Curves are not containers */ - return false; - - /* conditionally available */ - case ACHANNEL_SETTING_PROTECT: /* Protection is only valid when there's keyframes */ - if (fcu->bezt) - return true; - else - return false; // NOTE: in this special case, we need to draw ICON_ZOOMOUT - - case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */ - return (ac->spacetype == SPACE_IPO); - - /* always available */ - default: - return true; + /* unknown property... */ + BLI_snprintf(name, 256, "%s[%d]", fcu->rna_path, fcu->array_index); } } -/* get the appropriate flag(s) for the setting when it is valid */ -static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg) -{ - /* clear extra return data first */ - *neg = false; - - switch (setting) { - case ACHANNEL_SETTING_SELECT: /* selected */ - return FCURVE_SELECTED; - - case ACHANNEL_SETTING_MUTE: /* muted */ - return FCURVE_MUTED; - - case ACHANNEL_SETTING_PROTECT: /* protected */ - return FCURVE_PROTECTED; - - case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */ - return FCURVE_VISIBLE; - - default: /* unsupported */ - return 0; - } -} - -/* get pointer to the setting */ -static void *acf_fcurve_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type) -{ - FCurve *fcu = (FCurve *)ale->data; - - /* all flags are just in agrp->flag for now... */ - return GET_ACF_FLAG_PTR(fcu->flag, type); -} -/* fcurve type define */ -static bAnimChannelType ACF_FCURVE = +/* NLA Control F-Curve type define */ +static bAnimChannelType ACF_NLACURVE = { - "F-Curve", /* type name */ + "NLA Control F-Curve", /* type name */ ACHANNEL_ROLE_CHANNEL, /* role */ acf_generic_channel_color, /* backdrop color */ acf_generic_channel_backdrop, /* backdrop */ - acf_generic_indention_flexible, /* indent level */ // xxx rename this to f-curves only? + acf_generic_indention_1, /* indent level */ acf_generic_group_offset, /* offset */ - acf_fcurve_name, /* name */ + acf_nla_curve_name, /* name */ acf_fcurve_name_prop, /* name prop */ NULL, /* icon */ @@ -3323,6 +3366,7 @@ static void ANIM_init_channel_typeinfo_data(void) 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 */ @@ -3593,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 @@ -3639,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); @@ -3706,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; } @@ -3895,7 +3939,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"); @@ -3930,7 +3974,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)) { @@ -4199,7 +4243,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; @@ -4207,7 +4251,12 @@ 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) { + // TODO... + } + } + 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..85a4fd49b73 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; @@ -2727,7 +2731,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 +2749,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; diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index b5d1de9c7d6..76bede8edaa 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -1330,6 +1330,7 @@ static size_t animfilter_nla_controls(ListBase *anim_data, bDopeSheet *ads, Anim 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; @@ -1338,7 +1339,36 @@ static size_t animfilter_nla_controls(ListBase *anim_data, bDopeSheet *ads, Anim /* 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) { - tmp_items += animfilter_fcurves(&tmp_data, ads, strip->fcurves.first, NULL, filter_mode, owner_id); + 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; } } } @@ -1346,8 +1376,6 @@ static size_t animfilter_nla_controls(ListBase *anim_data, bDopeSheet *ads, Anim /* did we find anything? */ if (tmp_items) { - /* TODO: apply extra tags to indicate the NLA mapping does not apply here! */ - /* add the expander as a channel first */ if (filter_mode & ANIMFILTER_LIST_CHANNELS) { /* currently these channels cannot be selected, so they should be skipped */ diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 829ea74f00f..9b4037ff455 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -116,12 +116,15 @@ typedef struct bAnimListElem { int index; /* for un-named data, the index of the data in its collection */ short update; /* (eAnim_Update_Flags) tag the element for updating */ + short datatype; /* (eAnim_KeyType) type of motion data to expect */ void *key_data; /* motion data - mostly F-Curves, but can be other types too */ struct ID *id; /* ID block that channel is attached to */ struct AnimData *adt; /* source of the animation data attached to ID block (for convenience) */ + + void *owner; /* for per-element F-Curves (e.g. NLA Control Curves), the element that this represents (e.g. NlaStrip) */ } bAnimListElem; @@ -142,6 +145,7 @@ typedef enum eAnim_ChannelType { ANIMTYPE_FCURVE, ANIMTYPE_NLACONTROLS, + ANIMTYPE_NLACURVE, ANIMTYPE_FILLACTD, ANIMTYPE_FILLDRIVERS, diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 95066b91725..0c2575e19f0 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -1156,7 +1156,7 @@ static void duplicate_action_keys(bAnimContext *ac) /* loop through filtered data and delete selected keys */ for (ale = anim_data.first; ale; ale = ale->next) { - if (ale->type == ANIMTYPE_FCURVE) + if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) duplicate_fcurve_keys((FCurve *)ale->key_data); else if (ale->type == ANIMTYPE_GPLAYER) ED_gplayer_frames_duplicate((bGPDlayer *)ale->data); diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index ddfca98a119..0f94baff082 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -1221,11 +1221,11 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_ agrp->flag |= AGRP_SELECTED; ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP); } - else if (ale->type == ANIMTYPE_FCURVE) { + else if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) { FCurve *fcu = ale->data; 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); } } } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 2c189b715c4..a74de31491a 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -3584,7 +3584,7 @@ static void createTransActionData(bContext *C, TransInfo *t) else cfra = (float)CFRA; - if (ale->type == ANIMTYPE_FCURVE) + if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) count += count_fcurve_keys(ale->key_data, t->frame_side, cfra); else if (ale->type == ANIMTYPE_GPLAYER) count += count_gplayer_frames(ale->data, t->frame_side, cfra); |