== 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.
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user