diff options
author | Joshua Leung <aligorith@gmail.com> | 2007-09-25 09:04:34 +0400 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2007-09-25 09:04:34 +0400 |
commit | 2d429e1d548c2049c2179574a783ea791c7132ed (patch) | |
tree | a55a0d3c12ba461deaa51ee53144e12992aad9ba /source/blender | |
parent | 4ad6ac1caddcecc7e6a00f316cf60ea4d8b2aa38 (diff) |
== Armature Animation Fixes ==
This commit fixes several bugs related to animating armatures. I've also tidied up the formatting in a few files along the way, and also commented the flags for this pose->flag.
What's new/fixed:
* Undo will no longer destroy entire un-keyframed poses. Now it behaves as expected, and only reverses the most recent change.
* On some files, POSE_DO_UNLOCK somehow got set on files and never cleared. The symptom of this was a file in which you suddenly could no longer pose an armature at all without using auto-keyframing. A check to prevent this from happening again has been added (it will also fix old files too)
Notes:
- Now, all PoseChannels get tagged with BONE_UNKEYED after they have been transformed. This flag prevents IPO data being flushed over these new values, even after undo.
- These tags only get removed on frame-changes or inserting new keyframes.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_action.h | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/action.c | 38 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/scene.c | 4 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_action_types.h | 21 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_armature_types.h | 3 | ||||
-rw-r--r-- | source/blender/src/edit.c | 73 | ||||
-rw-r--r-- | source/blender/src/editarmature.c | 5 | ||||
-rw-r--r-- | source/blender/src/editipo.c | 19 | ||||
-rw-r--r-- | source/blender/src/poseobject.c | 29 | ||||
-rw-r--r-- | source/blender/src/transform_conversions.c | 31 |
10 files changed, 148 insertions, 78 deletions
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 3caf0ad2cc6..68a6be04735 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -101,6 +101,9 @@ struct bPoseChannel *verify_pose_channel(struct bPose* pose, /* sets constraint flags */ void update_pose_constraint_flags(struct bPose *pose); +/* clears BONE_UNKEYED flags for frame changing */ +void framechange_poses_clear_unkeyed(void); + /** * Allocate a new bAction on the heap and copy * the contents of src into it. If src is NULL NULL is returned. diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index c333ece497d..8274e3253a9 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -351,6 +351,28 @@ void update_pose_constraint_flags(bPose *pose) } } +/* Clears all BONE_UNKEYED flags for every pose channel in every pose + * This should only be called on frame changing, when it is acceptable to + * do this. Otherwise, these flags should not get cleared as poses may get lost. + */ +void framechange_poses_clear_unkeyed(void) +{ + Object *ob; + bPose *pose; + bPoseChannel *pchan; + + /* This needs to be done for each object that has a pose */ + // TODO: proxies may/may not be correctly handled here... (this needs checking) + for (ob= G.main->object.first; ob; ob= ob->id.next) { + /* we only need to do this on objects with a pose */ + if ( (pose= ob->pose) ) { + for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) { + if (pchan->bone) + pchan->bone->flag &= ~BONE_UNKEYED; + } + } + } +} /* ************************ END Pose channels *************** */ @@ -680,9 +702,15 @@ void extract_pose_from_action(bPose *pose, bAction *act, float ctime) /* Copy the data from the action into the pose */ for (pchan= pose->chanbase.first; pchan; pchan=pchan->next) { + /* skip this pose channel if it has been tagged as having unkeyed poses */ + if ((pchan->bone) && (pchan->bone->flag & BONE_UNKEYED)) + continue; + + /* get action channel and clear pchan-transform flags */ achan= get_action_channel(act, pchan->name); pchan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE); - if(achan) { + + if (achan) { ipo = achan->ipo; if (ipo) { /* Evaluates and sets the internal ipo value */ @@ -1252,12 +1280,11 @@ static void do_nla(Object *ob, int blocktype) void do_all_pose_actions(Object *ob) { - - // only to have safe calls from editor + /* only to have safe calls from editor */ if(ob==NULL) return; if(ob->type!=OB_ARMATURE || ob->pose==NULL) return; - if(ob->pose->flag & POSE_LOCKED) { // no actions to execute while transform + if(ob->pose->flag & POSE_LOCKED) { /* no actions to execute while transform */ if(ob->pose->flag & POSE_DO_UNLOCK) ob->pose->flag &= ~(POSE_LOCKED|POSE_DO_UNLOCK); } @@ -1271,6 +1298,9 @@ void do_all_pose_actions(Object *ob) else if(ob->nlastrips.first) { do_nla(ob, ID_AR); } + + /* clear POSE_DO_UNLOCK flags that might have slipped through (just in case) */ + ob->pose->flag &= ~POSE_DO_UNLOCK; } /* called from where_is_object */ diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index ea4911906bd..7cce8c5e8c9 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -530,6 +530,9 @@ void scene_update_for_newframe(Scene *sce, unsigned int lay) { Scene *scene= sce; + /* clears all BONE_UNKEYED flags for every pose's pchans */ + framechange_poses_clear_unkeyed(); + /* object ipos are calculated in where_is_object */ do_all_data_ipos(); @@ -540,7 +543,6 @@ void scene_update_for_newframe(Scene *sce, unsigned int lay) scene_update(sce, lay); scene_update(scene, lay); - } /* return default layer, also used to patch old files */ diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 9ff07aeb453..5bdb4419b6e 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -148,18 +148,27 @@ typedef struct SpaceAction { #define ACHAN_MOVED 0x80000000 /* SpaceAction flag */ -#define SACTION_MOVING 1 /* during transform */ -#define SACTION_SLIDERS 2 /* show sliders (if relevant) - limited to shape keys for now */ -#define SACTION_DRAWTIME 4 /* draw time in seconds instead of time in frames */ + /* during transform */ +#define SACTION_MOVING 1 + /* show sliders (if relevant) - limited to shape keys for now */ +#define SACTION_SLIDERS 2 + /* draw time in seconds instead of time in frames */ +#define SACTION_DRAWTIME 4 /* SpaceAction AutoSnap Settings (also used by SpaceNLA) */ -#define SACTSNAP_OFF 0 /* no auto-snap */ -#define SACTSNAP_STEP 1 /* snap to 1.0 frame/second intervals */ -#define SACTSNAP_FRAME 2 /* snap to actual frames/seconds (nla-action time) */ + /* no auto-snap */ +#define SACTSNAP_OFF 0 + /* snap to 1.0 frame/second intervals */ +#define SACTSNAP_STEP 1 + /* snap to actual frames/seconds (nla-action time) */ +#define SACTSNAP_FRAME 2 /* Pose->flag */ + /* results in armature_rebuild_pose being called */ #define POSE_RECALC 1 + /* prevents any channel from getting overridden by anim from IPO */ #define POSE_LOCKED 2 + /* clears the POSE_LOCKED flag for the next time the pose is evaluated */ #define POSE_DO_UNLOCK 4 /* PoseChannel (transform) flags */ diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h index 53a5f26033c..31a95363802 100644 --- a/source/blender/makesdna/DNA_armature_types.h +++ b/source/blender/makesdna/DNA_armature_types.h @@ -145,6 +145,7 @@ typedef struct bArmature { /* multiplies vgroup with envelope */ #define BONE_MULT_VG_ENV 2048 #define BONE_NO_DEFORM 4096 - + /* set to prevent destruction of its unkeyframed pose (after transform) */ +#define BONE_UNKEYED 8192 #endif diff --git a/source/blender/src/edit.c b/source/blender/src/edit.c index fb62c33abe8..7d784dcecfd 100644 --- a/source/blender/src/edit.c +++ b/source/blender/src/edit.c @@ -1158,13 +1158,13 @@ void snap_sel_to_grid() if ELEM6(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL) make_trans_verts(bmat[0], bmat[1], 0); if(tottrans==0) return; - + Mat3CpyMat4(bmat, G.obedit->obmat); Mat3Inv(imat, bmat); - + tv= transvmain; for(a=0; a<tottrans; a++, tv++) { - + VECCOPY(vec, tv->loc); Mat3MulVecfl(bmat, vec); VecAddf(vec, vec, G.obedit->obmat[3]); @@ -1172,17 +1172,17 @@ void snap_sel_to_grid() vec[1]= G.vd->gridview*floor(.5+ vec[1]/gridf); vec[2]= G.vd->gridview*floor(.5+ vec[2]/gridf); VecSubf(vec, vec, G.obedit->obmat[3]); - + Mat3MulVecfl(imat, vec); VECCOPY(tv->loc, vec); - + } - + special_transvert_update(); MEM_freeN(transvmain); transvmain= 0; - + allqueue(REDRAWVIEW3D, 0); return; } @@ -1274,31 +1274,29 @@ void snap_sel_to_curs() if(G.obedit) { tottrans= 0; - + if ELEM6(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL) make_trans_verts(bmat[0], bmat[1], 0); if(tottrans==0) return; - + Mat3CpyMat4(bmat, G.obedit->obmat); Mat3Inv(imat, bmat); - + tv= transvmain; for(a=0; a<tottrans; a++, tv++) { - vec[0]= curs[0]-G.obedit->obmat[3][0]; vec[1]= curs[1]-G.obedit->obmat[3][1]; vec[2]= curs[2]-G.obedit->obmat[3][2]; - + Mat3MulVecfl(imat, vec); VECCOPY(tv->loc, vec); - } special_transvert_update(); MEM_freeN(transvmain); transvmain= 0; - + allqueue(REDRAWVIEW3D, 0); return; } @@ -1346,10 +1344,10 @@ void snap_sel_to_curs() vec[0]= -ob->obmat[3][0] + curs[0]; vec[1]= -ob->obmat[3][1] + curs[1]; vec[2]= -ob->obmat[3][2] + curs[2]; - + if(ob->parent) { where_is_object(ob); - + Mat3Inv(imat, originmat); Mat3MulVecfl(imat, vec); ob->loc[0]+= vec[0]; @@ -1388,7 +1386,6 @@ void snap_curs_to_grid() curs[2]= G.vd->gridview*floor(.5+curs[2]/gridf); allqueue(REDRAWVIEW3D, 0); - } void snap_curs_to_sel() @@ -1406,13 +1403,13 @@ void snap_curs_to_sel() if(G.obedit) { tottrans=0; - + if ELEM6(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL) make_trans_verts(bmat[0], bmat[1], 2); if(tottrans==0) return; - + Mat3CpyMat4(bmat, G.obedit->obmat); - + tv= transvmain; for(a=0; a<tottrans; a++, tv++) { VECCOPY(vec, tv->loc); @@ -1421,7 +1418,7 @@ void snap_curs_to_sel() VecAddf(centroid, centroid, vec); DO_MINMAX(vec, min, max); } - + if(G.vd->around==V3D_CENTROID) { VecMulf(centroid, 1.0/(float)tottrans); VECCOPY(curs, centroid); @@ -1492,20 +1489,20 @@ void snap_curs_to_firstsel() if(G.obedit) { tottrans=0; - + if ELEM6(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL) make_trans_verts(bmat[0], bmat[1], 0); if(tottrans==0) return; - + Mat3CpyMat4(bmat, G.obedit->obmat); - + tv= transvmain; VECCOPY(vec, tv->loc); /*Mat3MulVecfl(bmat, vec); VecAddf(vec, vec, G.obedit->obmat[3]); VecAddf(centroid, centroid, vec); DO_MINMAX(vec, min, max);*/ - + if(G.vd->around==V3D_CENTROID) { VecMulf(vec, 1.0/(float)tottrans); VECCOPY(curs, vec); @@ -1561,14 +1558,14 @@ void snap_to_center() if(G.obedit) { tottrans= 0; - + if ELEM6(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL) make_trans_verts(bmat[0], bmat[1], 0); if(tottrans==0) return; - + Mat3CpyMat4(bmat, G.obedit->obmat); Mat3Inv(imat, bmat); - + tv= transvmain; for(a=0; a<tottrans; a++, tv++) { VECCOPY(vec, tv->loc); @@ -1577,7 +1574,7 @@ void snap_to_center() VecAddf(centroid, centroid, vec); DO_MINMAX(vec, min, max); } - + if(G.vd->around==V3D_CENTROID) { VecMulf(centroid, 1.0/(float)tottrans); VECCOPY(snaploc, centroid); @@ -1590,7 +1587,6 @@ void snap_to_center() MEM_freeN(transvmain); transvmain= 0; - } else { base= (G.scene->base.first); @@ -1638,21 +1634,20 @@ void snap_to_center() /* Snap the selection to the snaplocation (duh!) */ if(G.obedit) { tottrans= 0; - + if ELEM6(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL) make_trans_verts(bmat[0], bmat[1], 0); if(tottrans==0) return; - + Mat3CpyMat4(bmat, G.obedit->obmat); Mat3Inv(imat, bmat); - + tv= transvmain; for(a=0; a<tottrans; a++, tv++) { - vec[0]= snaploc[0]-G.obedit->obmat[3][0]; vec[1]= snaploc[1]-G.obedit->obmat[3][1]; vec[2]= snaploc[2]-G.obedit->obmat[3][2]; - + Mat3MulVecfl(imat, vec); VECCOPY(tv->loc, vec); } @@ -1661,7 +1656,7 @@ void snap_to_center() MEM_freeN(transvmain); transvmain= 0; - + allqueue(REDRAWVIEW3D, 0); return; } @@ -1702,10 +1697,10 @@ void snap_to_center() vec[0]= -ob->obmat[3][0] + snaploc[0]; vec[1]= -ob->obmat[3][1] + snaploc[1]; vec[2]= -ob->obmat[3][2] + snaploc[2]; - + if(ob->parent) { where_is_object(ob); - + Mat3Inv(imat, originmat); Mat3MulVecfl(imat, vec); ob->loc[0]+= vec[0]; @@ -1725,7 +1720,7 @@ void snap_to_center() autokeyframe_ob_cb_func(ob, TFM_TRANSLATION); } } - + base= base->next; } DAG_scene_flush_update(G.scene, screen_view3d_layers()); diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 12d58ad535a..81467b95297 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -2221,7 +2221,7 @@ void clear_armature(Object *ob, char mode) for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { if(pchan->bone && (pchan->bone->flag & BONE_SELECTED)) { if(arm->layer & pchan->bone->layer) { - switch (mode){ + switch (mode) { case 'r': pchan->quat[1]=pchan->quat[2]=pchan->quat[3]=0.0F; pchan->quat[0]=1.0F; break; @@ -2233,6 +2233,9 @@ void clear_armature(Object *ob, char mode) break; } + + /* the current values from IPO's may not be zero, so tag as unkeyed */ + pchan->bone->flag |= BONE_UNKEYED; } } } diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index f65e70ce59e..75cded52010 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -3016,7 +3016,7 @@ void common_insertkey(void) if (ob && (ob->flag & OB_POSEMODE)) { bPoseChannel *pchan; - set_pose_keys(ob); // sets pchan->flag to POSE_KEY if bone selected + set_pose_keys(ob); /* sets pchan->flag to POSE_KEY if bone selected, and clears if not */ for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) if (pchan->flag & POSE_KEY) break; @@ -3058,13 +3058,14 @@ void common_insertkey(void) id= &ob->id; for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) { - if (pchan->flag & POSE_KEY){ + if (pchan->flag & POSE_KEY) { + /* insert relevant keyframes */ if(event==0 || event==3 ||event==4) { insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, 0); insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0); insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0); } - if(event==1 || event==3 ||event==4) { + if(event==1 || event==3 || event==4) { insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0); insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0); insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0); @@ -3077,7 +3078,7 @@ void common_insertkey(void) } if (event==9 && ob->action) { bActionChannel *achan; - + for (achan = ob->action->chanbase.first; achan; achan=achan->next){ if (achan->ipo && !strcmp (achan->name, pchan->name)){ for (icu = achan->ipo->curve.first; icu; icu=icu->next){ @@ -3088,11 +3089,9 @@ void common_insertkey(void) } } if(event==11 || event==13) { - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_X); insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y); insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z); - } if(event==12 || event==13) { int matsuccess=0; @@ -3111,7 +3110,7 @@ void common_insertkey(void) } if (event==15 && ob->action) { bActionChannel *achan; - + for (achan = ob->action->chanbase.first; achan; achan=achan->next){ if (achan->ipo && !strcmp (achan->name, pchan->name)){ for (icu = achan->ipo->curve.first; icu; icu=icu->next){ @@ -3120,7 +3119,11 @@ void common_insertkey(void) break; } } - } + } + + /* clear unkeyed flag (it doesn't matter if it's set or not) */ + if (pchan->bone) + pchan->bone->flag &= ~BONE_UNKEYED; } } if(ob->action) diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c index ab6d3f47eeb..f36b392775e 100644 --- a/source/blender/src/poseobject.c +++ b/source/blender/src/poseobject.c @@ -680,7 +680,7 @@ void paste_posebuf (int flip) /* Safely merge all of the channels in this pose into any existing pose */ - for (chan=g_posebuf->chanbase.first; chan; chan=chan->next){ + for (chan=g_posebuf->chanbase.first; chan; chan=chan->next) { if (chan->flag & POSE_KEY) { BLI_strncpy(name, chan->name, sizeof(name)); if (flip) @@ -689,7 +689,7 @@ void paste_posebuf (int flip) /* only copy when channel exists, poses are not meant to add random channels to anymore */ pchan= get_pose_channel(ob->pose, name); - if(pchan) { + if (pchan) { /* only loc rot size */ /* only copies transform info for the pose */ VECCOPY(pchan->loc, chan->loc); @@ -697,35 +697,44 @@ void paste_posebuf (int flip) QUATCOPY(pchan->quat, chan->quat); pchan->flag= chan->flag; - if (flip){ + if (flip) { pchan->loc[0]*= -1; - + QuatToEul(pchan->quat, eul); eul[1]*= -1; eul[2]*= -1; EulToQuat(eul, pchan->quat); } - - if (G.flags & G_RECORDKEYS){ + + if (G.flags & G_RECORDKEYS) { ID *id= &ob->id; - + /* Set keys on pose */ - if (chan->flag & POSE_ROT){ + if (chan->flag & POSE_ROT) { insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0); insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0); insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0); insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0); } - if (chan->flag & POSE_SIZE){ + if (chan->flag & POSE_SIZE) { insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, 0); insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y, 0); insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z, 0); } - if (chan->flag & POSE_LOC){ + if (chan->flag & POSE_LOC) { insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, 0); insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0); insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0); } + + /* clear any unkeyed tags */ + if (chan->bone) + chan->bone->flag &= ~BONE_UNKEYED; + } + else { + /* add unkeyed tags */ + if (chan->bone) + chan->bone->flag |= BONE_UNKEYED; } } } diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 31002134d55..058461806ce 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -2607,15 +2607,19 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) if (!act) act= ob->action= add_empty_action("Action"); - for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){ - if (pchan->bone->flag & BONE_TRANSFORM){ - + for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) { + if (pchan->bone->flag & BONE_TRANSFORM) { + /* clear any 'unkeyed' flag it may have */ + pchan->bone->flag &= ~BONE_UNKEYED; + + /* only insert into available channels? */ if(U.uiflag & USER_KEYINSERTAVAI) { bActionChannel *achan; - + for (achan = act->chanbase.first; achan; achan=achan->next){ if (achan->ipo && !strcmp (achan->name, pchan->name)){ for (icu = achan->ipo->curve.first; icu; icu=icu->next){ + /* only insert keyframe if needed? */ if (U.uiflag & USER_KEYINSERTNEED) insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode); else @@ -2625,6 +2629,7 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) } } } + /* only insert keyframe if needed? */ else if (U.uiflag & USER_KEYINSERTNEED) { if ((tmode==TFM_TRANSLATION) && (targetless_ik==0)) { insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_X); @@ -2643,16 +2648,17 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Z); } } + /* insert keyframe in any channel that's appropriate */ else { insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_X, 0); insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Y, 0); insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Z, 0); - + insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0); insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0); insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0); insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0); - + insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_X, 0); insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0); insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0); @@ -2667,6 +2673,15 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) allqueue(REDRAWNLA, 0); allqueue(REDRAWTIME, 0); } + else { + /* tag channels that should have unkeyed data */ + for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) { + if (pchan->bone->flag & BONE_TRANSFORM) { + /* tag this channel */ + pchan->bone->flag |= BONE_UNKEYED; + } + } + } } /* very bad call!!! - copied from editnla.c! */ @@ -2775,8 +2790,8 @@ void special_aftertrans_update(TransInfo *t) if(t->mode==TFM_TRANSLATION) pose_grab_with_ik_clear(ob); - - /* automatic inserting of keys */ + + /* automatic inserting of keys and unkeyed tagging - only if transform wasn't cancelled */ if(!cancelled) { autokeyframe_pose_cb_func(ob, t->mode, targetless_ik); DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); |