Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2015-03-30 11:50:59 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2015-03-30 11:50:59 +0300
commitd7ddffdcce6db03e63c09c566b57a1252101058f (patch)
treeae967c1bafeaf6abbe76012772d49ea488076fe6 /source/blender/editors/animation
parenta5180abde0b5b958b331c026d4cd1628b6d2c747 (diff)
parent59740a6c985efbf5369d27a5919e184036d0287a (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.c219
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c96
-rw-r--r--source/blender/editors/animation/anim_draw.c12
-rw-r--r--source/blender/editors/animation/anim_filter.c98
-rw-r--r--source/blender/editors/animation/keyframing.c48
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 {