Bugfix #19576: Auto keyframing does not record rotations on object level animation

The hardcoded paths for rotation keyframes on objects got broken by my commits to rename the rotation properties. I've taken this opportunity to recode the auto-keyframing code here to use the builtin keyingsets instead of going through and manually calling insert_keyframe(), thus preventing this problem in future.
This commit is contained in:
Joshua Leung 2009-10-08 05:53:26 +00:00
parent b4b031eae7
commit 6e43a69a8d
7 changed files with 72 additions and 115 deletions

@ -981,12 +981,15 @@ static int insert_key_exec (bContext *C, wmOperator *op)
} }
/* try to insert keyframes for the channels specified by KeyingSet */ /* try to insert keyframes for the channels specified by KeyingSet */
success= modify_keyframes(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); success= modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
printf("KeyingSet '%s' - Successfully added %d Keyframes \n", ks->name, success); if (G.f & G_DEBUG)
printf("KeyingSet '%s' - Successfully added %d Keyframes \n", ks->name, success);
/* report failure? */ /* report failure? */
if (success == 0) if (success == 0)
BKE_report(op->reports, RPT_WARNING, "Keying Set failed to insert any keyframes"); BKE_report(op->reports, RPT_WARNING, "Keying Set failed to insert any keyframes");
else
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
/* free temp context-data if available */ /* free temp context-data if available */
if (dsources.first) { if (dsources.first) {
@ -995,10 +998,7 @@ static int insert_key_exec (bContext *C, wmOperator *op)
} }
/* send updates */ /* send updates */
ED_anim_dag_flush_update(C); ED_anim_dag_flush_update(C);
/* for now, only send ND_KEYS for KeyingSets */
WM_event_add_notifier(C, ND_KEYS, NULL);
return OPERATOR_FINISHED; return OPERATOR_FINISHED;
} }
@ -1132,12 +1132,15 @@ static int delete_key_exec (bContext *C, wmOperator *op)
} }
/* try to insert keyframes for the channels specified by KeyingSet */ /* try to insert keyframes for the channels specified by KeyingSet */
success= modify_keyframes(C, &dsources, NULL, ks, MODIFYKEY_MODE_DELETE, cfra); success= modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_DELETE, cfra);
printf("KeyingSet '%s' - Successfully removed %d Keyframes \n", ks->name, success); if (G.f & G_DEBUG)
printf("KeyingSet '%s' - Successfully removed %d Keyframes \n", ks->name, success);
/* report failure? */ /* report failure? */
if (success == 0) if (success == 0)
BKE_report(op->reports, RPT_WARNING, "Keying Set failed to remove any keyframes"); BKE_report(op->reports, RPT_WARNING, "Keying Set failed to remove any keyframes");
else
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
/* free temp context-data if available */ /* free temp context-data if available */
if (dsources.first) { if (dsources.first) {
@ -1148,9 +1151,6 @@ static int delete_key_exec (bContext *C, wmOperator *op)
/* send updates */ /* send updates */
ED_anim_dag_flush_update(C); ED_anim_dag_flush_update(C);
/* for now, only send ND_KEYS for KeyingSets */
WM_event_add_notifier(C, ND_KEYS, NULL);
return OPERATOR_FINISHED; return OPERATOR_FINISHED;
} }

@ -1252,9 +1252,8 @@ short modifykey_get_context_data (bContext *C, ListBase *dsources, KeyingSet *ks
* by the KeyingSet. This takes into account many of the different combinations of using KeyingSets. * by the KeyingSet. This takes into account many of the different combinations of using KeyingSets.
* Returns the number of channels that keyframes were added to * Returns the number of channels that keyframes were added to
*/ */
int modify_keyframes (bContext *C, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra) int modify_keyframes (Scene *scene, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra)
{ {
Scene *scene= CTX_data_scene(C);
KS_Path *ksp; KS_Path *ksp;
int kflag=0, success= 0; int kflag=0, success= 0;
char *groupname= NULL; char *groupname= NULL;
@ -1319,24 +1318,16 @@ int modify_keyframes (bContext *C, ListBase *dsources, bAction *act, KeyingSet *
success+= delete_keyframe(ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag); success+= delete_keyframe(ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag);
} }
/* send notifiers and set recalc-flags */ /* set recalc-flags */
// TODO: hopefully this doesn't result in execessive flooding of the notifier stack if (ksp->id) {
if (C && ksp->id) {
switch (GS(ksp->id->name)) { switch (GS(ksp->id->name)) {
case ID_OB: /* Object (or Object-Related) Keyframes */ case ID_OB: /* Object (or Object-Related) Keyframes */
{ {
Object *ob= (Object *)ksp->id; Object *ob= (Object *)ksp->id;
ob->recalc |= OB_RECALC; ob->recalc |= OB_RECALC;
WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, ksp->id);
} }
break; break;
case ID_MA: /* Material Keyframes */
WM_event_add_notifier(C, NC_MATERIAL|ND_KEYS, ksp->id);
break;
default: /* Any keyframes */
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
break;
} }
} }
} }
@ -1457,24 +1448,16 @@ int modify_keyframes (bContext *C, ListBase *dsources, bAction *act, KeyingSet *
MEM_freeN(path); MEM_freeN(path);
} }
/* send notifiers and set recalc-flags */ /* set recalc-flags */
// TODO: hopefully this doesn't result in execessive flooding of the notifier stack if (cks->id) {
if (C && cks->id) {
switch (GS(cks->id->name)) { switch (GS(cks->id->name)) {
case ID_OB: /* Object (or Object-Related) Keyframes */ case ID_OB: /* Object (or Object-Related) Keyframes */
{ {
Object *ob= (Object *)cks->id; Object *ob= (Object *)cks->id;
ob->recalc |= OB_RECALC; ob->recalc |= OB_RECALC;
WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, cks->id);
} }
break; break;
case ID_MA: /* Material Keyframes */
WM_event_add_notifier(C, NC_MATERIAL|ND_KEYS, cks->id);
break;
default: /* Any keyframes */
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
break;
} }
} }
} }

@ -560,11 +560,11 @@ static void pose_slide_autoKeyframe (bContext *C, tPoseSlideOp *pso)
/* insert keyframes */ /* insert keyframes */
if (pchan->flag & POSE_LOC) if (pchan->flag & POSE_LOC)
modify_keyframes(C, &dsources, NULL, pso->ks_loc, MODIFYKEY_MODE_INSERT, (float)pso->cframe); modify_keyframes(pso->scene, &dsources, NULL, pso->ks_loc, MODIFYKEY_MODE_INSERT, (float)pso->cframe);
if (pchan->flag & POSE_ROT) if (pchan->flag & POSE_ROT)
modify_keyframes(C, &dsources, NULL, pso->ks_rot, MODIFYKEY_MODE_INSERT, (float)pso->cframe); modify_keyframes(pso->scene, &dsources, NULL, pso->ks_rot, MODIFYKEY_MODE_INSERT, (float)pso->cframe);
if (pchan->flag & POSE_SIZE) if (pchan->flag & POSE_SIZE)
modify_keyframes(C, &dsources, NULL, pso->ks_scale, MODIFYKEY_MODE_INSERT, (float)pso->cframe); modify_keyframes(pso->scene, &dsources, NULL, pso->ks_scale, MODIFYKEY_MODE_INSERT, (float)pso->cframe);
} }
} }
} }

@ -329,6 +329,7 @@ static int poselib_add_menu_invoke (bContext *C, wmOperator *op, wmEvent *evt)
static int poselib_add_exec (bContext *C, wmOperator *op) static int poselib_add_exec (bContext *C, wmOperator *op)
{ {
Scene *scene= CTX_data_scene(C);
Object *ob= CTX_data_active_object(C); Object *ob= CTX_data_active_object(C);
bAction *act = poselib_validate(ob); bAction *act = poselib_validate(ob);
bArmature *arm= (ob) ? ob->data : NULL; bArmature *arm= (ob) ? ob->data : NULL;
@ -385,7 +386,7 @@ static int poselib_add_exec (bContext *C, wmOperator *op)
/* KeyingSet to use depends on rotation mode (but that's handled by the templates code) */ /* KeyingSet to use depends on rotation mode (but that's handled by the templates code) */
if (poselib_ks_locrotscale == NULL) if (poselib_ks_locrotscale == NULL)
poselib_ks_locrotscale= ANIM_builtin_keyingset_get_named(NULL, "LocRotScale"); poselib_ks_locrotscale= ANIM_builtin_keyingset_get_named(NULL, "LocRotScale");
modify_keyframes(C, &dsources, act, poselib_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)frame); modify_keyframes(scene, &dsources, act, poselib_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)frame);
} }
} }
} }
@ -772,7 +773,7 @@ static void poselib_keytag_pose (bContext *C, Scene *scene, tPoseLib_PreviewData
cks.pchan= pchan; cks.pchan= pchan;
/* now insert the keyframe */ /* now insert the keyframe */
modify_keyframes(C, &dsources, NULL, poselib_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)CFRA); modify_keyframes(scene, &dsources, NULL, poselib_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)CFRA);
/* clear any unkeyed tags */ /* clear any unkeyed tags */
if (pchan->bone) if (pchan->bone)
@ -783,10 +784,12 @@ static void poselib_keytag_pose (bContext *C, Scene *scene, tPoseLib_PreviewData
if (pchan->bone) if (pchan->bone)
pchan->bone->flag |= BONE_UNKEYED; pchan->bone->flag |= BONE_UNKEYED;
} }
} }
} }
} }
/* send notifiers for this */
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
} }
/* Apply the relevant changes to the pose */ /* Apply the relevant changes to the pose */

@ -1089,7 +1089,7 @@ static int pose_paste_exec (bContext *C, wmOperator *op)
/* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */ /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
cks.pchan= pchan; cks.pchan= pchan;
modify_keyframes(C, &dsources, NULL, posePaste_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)CFRA); modify_keyframes(scene, &dsources, NULL, posePaste_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)CFRA);
/* clear any unkeyed tags */ /* clear any unkeyed tags */
if (chan->bone) if (chan->bone)
@ -1118,6 +1118,7 @@ static int pose_paste_exec (bContext *C, wmOperator *op)
/* notifiers for updates */ /* notifiers for updates */
WM_event_add_notifier(C, NC_OBJECT|ND_POSE|ND_TRANSFORM, ob); WM_event_add_notifier(C, NC_OBJECT|ND_POSE|ND_TRANSFORM, ob);
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); // XXX not really needed, but here for completeness...
return OPERATOR_FINISHED; return OPERATOR_FINISHED;
} }

@ -122,7 +122,7 @@ enum {
} eModifyKey_Modes; } eModifyKey_Modes;
/* Keyframing Helper Call - use the provided Keying Set to Add/Remove Keyframes */ /* Keyframing Helper Call - use the provided Keying Set to Add/Remove Keyframes */
int modify_keyframes(struct bContext *C, struct ListBase *dsources, struct bAction *act, struct KeyingSet *ks, short mode, float cfra); int modify_keyframes(struct Scene *scene, struct ListBase *dsources, struct bAction *act, struct KeyingSet *ks, short mode, float cfra);
/* -------- */ /* -------- */

@ -4242,10 +4242,15 @@ void autokeyframe_ob_cb_func(Scene *scene, View3D *v3d, Object *ob, int tmode)
// TODO: this should probably be done per channel instead... // TODO: this should probably be done per channel instead...
if (autokeyframe_cfra_can_key(scene, id)) { if (autokeyframe_cfra_can_key(scene, id)) {
AnimData *adt= ob->adt; bCommonKeySrc cks;
ListBase dsources = {&cks, &cks};
float cfra= (float)CFRA; // xxx this will do for now float cfra= (float)CFRA; // xxx this will do for now
short flag = 0; short flag = 0;
/* init common-key-source for use by KeyingSets */
memset(&cks, 0, sizeof(bCommonKeySrc));
cks.id= &ob->id;
if (IS_AUTOKEY_FLAG(INSERTNEEDED)) if (IS_AUTOKEY_FLAG(INSERTNEEDED))
flag |= INSERTKEY_NEEDED; flag |= INSERTKEY_NEEDED;
if (IS_AUTOKEY_FLAG(AUTOMATKEY)) if (IS_AUTOKEY_FLAG(AUTOMATKEY))
@ -4254,6 +4259,8 @@ void autokeyframe_ob_cb_func(Scene *scene, View3D *v3d, Object *ob, int tmode)
flag |= INSERTKEY_REPLACE; flag |= INSERTKEY_REPLACE;
if (IS_AUTOKEY_FLAG(INSERTAVAIL)) { if (IS_AUTOKEY_FLAG(INSERTAVAIL)) {
AnimData *adt= ob->adt;
/* only key on available channels */ /* only key on available channels */
if (adt && adt->action) { if (adt && adt->action) {
for (fcu= adt->action->curves.first; fcu; fcu= fcu->next) { for (fcu= adt->action->curves.first; fcu; fcu= fcu->next) {
@ -4292,41 +4299,25 @@ void autokeyframe_ob_cb_func(Scene *scene, View3D *v3d, Object *ob, int tmode)
doScale = 1; doScale = 1;
} }
// TODO: the group names here are temporary... /* insert keyframes for the affected sets of channels using the builtin KeyingSets found */
// TODO: should this be made to use the builtin KeyingSets instead?
if (doLoc) { if (doLoc) {
insert_keyframe(id, NULL, "Object Transform", "location", 0, cfra, flag); KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Location");
insert_keyframe(id, NULL, "Object Transform", "location", 1, cfra, flag); modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
insert_keyframe(id, NULL, "Object Transform", "location", 2, cfra, flag);
} }
if (doRot) { if (doRot) {
insert_keyframe(id, NULL, "Object Transform", "rotation", 0, cfra, flag); KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Rotation");
insert_keyframe(id, NULL, "Object Transform", "rotation", 1, cfra, flag); modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
insert_keyframe(id, NULL, "Object Transform", "rotation", 2, cfra, flag);
} }
if (doScale) { if (doScale) {
insert_keyframe(id, NULL, "Object Transform", "scale", 0, cfra, flag); KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Scale");
insert_keyframe(id, NULL, "Object Transform", "scale", 1, cfra, flag); modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
insert_keyframe(id, NULL, "Object Transform", "scale", 2, cfra, flag);
} }
} }
/* insert keyframe in all (transform) channels */
else { else {
// TODO: the group names here are temporary... KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "LocRotScale");
// TODO: should this be made to use the builtin KeyingSets instead? modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
insert_keyframe(id, NULL, "Object Transform", "location", 0, cfra, flag);
insert_keyframe(id, NULL, "Object Transform", "location", 1, cfra, flag);
insert_keyframe(id, NULL, "Object Transform", "location", 2, cfra, flag);
insert_keyframe(id, NULL, "Object Transform", "rotation", 0, cfra, flag);
insert_keyframe(id, NULL, "Object Transform", "rotation", 1, cfra, flag);
insert_keyframe(id, NULL, "Object Transform", "rotation", 2, cfra, flag);
insert_keyframe(id, NULL, "Object Transform", "scale", 0, cfra, flag);
insert_keyframe(id, NULL, "Object Transform", "scale", 1, cfra, flag);
insert_keyframe(id, NULL, "Object Transform", "scale", 2, cfra, flag);
} }
// XXX todo... find a way to send notifiers from here...
} }
} }
@ -4346,9 +4337,14 @@ void autokeyframe_pose_cb_func(Scene *scene, View3D *v3d, Object *ob, int tmode,
// TODO: this should probably be done per channel instead... // TODO: this should probably be done per channel instead...
if (autokeyframe_cfra_can_key(scene, id)) { if (autokeyframe_cfra_can_key(scene, id)) {
bCommonKeySrc cks;
ListBase dsources = {&cks, &cks};
float cfra= (float)CFRA; float cfra= (float)CFRA;
short flag= 0; short flag= 0;
char buf[512];
/* init common-key-source for use by KeyingSets */
memset(&cks, 0, sizeof(bCommonKeySrc));
cks.id= &ob->id;
/* flag is initialised from UserPref keyframing settings /* flag is initialised from UserPref keyframing settings
* - special exception for targetless IK - INSERTKEY_MATRIX keyframes should get * - special exception for targetless IK - INSERTKEY_MATRIX keyframes should get
@ -4401,60 +4397,34 @@ void autokeyframe_pose_cb_func(Scene *scene, View3D *v3d, Object *ob, int tmode,
} }
if (doLoc) { if (doLoc) {
sprintf(buf, "pose.pose_channels[\"%s\"].location", pchan->name); KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Location");
insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag);
insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag); /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag); cks.pchan= pchan;
modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
} }
if (doRot) { if (doRot) {
// FIXME: better to just use the keyingsets for this instead... KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Rotation");
if (pchan->rotmode == ROT_MODE_QUAT) {
sprintf(buf, "pose.pose_channels[\"%s\"].rotation_quaternion", pchan->name); /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag); cks.pchan= pchan;
insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag); modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag);
insert_keyframe(id, NULL, pchan->name, buf, 3, cfra, flag);
}
else {
sprintf(buf, "pose.pose_channels[\"%s\"].rotation_euler", pchan->name);
insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag);
insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag);
insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag);
}
} }
if (doScale) { if (doScale) {
sprintf(buf, "pose.pose_channels[\"%s\"].scale", pchan->name); KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Scale");
insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag);
insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag); /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag); cks.pchan= pchan;
modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
} }
} }
/* insert keyframe in any channel that's appropriate */ /* insert keyframe in all (transform) channels */
else { else {
sprintf(buf, "pose.pose_channels[\"%s\"].location", pchan->name); KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "LocRotScale");
insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag);
insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag);
insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag);
// FIXME: better to just use the keyingsets for this instead... /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
if (pchan->rotmode == ROT_MODE_QUAT) { cks.pchan= pchan;
sprintf(buf, "pose.pose_channels[\"%s\"].rotation", pchan->name); modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag);
insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag);
insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag);
insert_keyframe(id, NULL, pchan->name, buf, 3, cfra, flag);
}
else {
sprintf(buf, "pose.pose_channels[\"%s\"].rotation_euler", pchan->name);
insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag);
insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag);
insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag);
}
sprintf(buf, "pose.pose_channels[\"%s\"].scale", pchan->name);
insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag);
insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag);
insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag);
} }
} }
} }