Nla Strip Controls: Added special FCurve type (in the animfiltering code)

Using the standard "FCurve" animchannel type didn't work that well for
the control FCurves on NLA Strips, as the paths would not resolve correctly,
and the indentation was wrong. Also, there would likely be issues down the
track with applying NLA mapping. Hence, it's easier to just create a separate
type for this case, and adapt the rest of the code to also consider these (todo).
This commit is contained in:
Joshua Leung 2015-03-22 21:41:45 +13:00
parent 8f4c5ff0ec
commit 67f983ac53
7 changed files with 202 additions and 116 deletions

View File

@ -908,106 +908,6 @@ static bAnimChannelType ACF_GROUP =
acf_group_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 *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 *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 *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 */
};
/* F-Curve ------------------------------------------- */
/* name for fcurve entries */
@ -1117,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 *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 *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 *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?
@ -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;

View File

@ -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;

View File

@ -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 */

View File

@ -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,

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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);