Bugfix [#27157] keyframing a constrained bone does not work as before
authorJoshua Leung <aligorith@gmail.com>
Sat, 16 Jul 2011 06:46:39 +0000 (06:46 +0000)
committerJoshua Leung <aligorith@gmail.com>
Sat, 16 Jul 2011 06:46:39 +0000 (06:46 +0000)
Visual Keyframing was broken by r.34685, which used another method
which, at the time, appeared to work perfectly fine. Apparently not.

Also, extend/fixed visual keying to work for axis-angle rotations too.
Needs some testing, but should probably work

1  2 
source/blender/editors/animation/keyframing.c

index 1ba695209b2e9f672950c086ff8f616d4b6b4e8c,8dc813d940b023723d8bbdd3e072bd2329057029..109da669ce6e3fac118192ec39c0c88855bc17c4
@@@ -661,41 -648,41 +661,72 @@@ static float visualkey_get_value (Point
                                mat4_to_eulO(eul, ob->rotmode, ob->obmat);
                                return eul[array_index];
                        }
-                       // FIXME: other types of rotation don't work
++                      else if (strstr(identifier, "rotation_quaternion")) {
++                              float trimat[3][3], quat[4];
++                              
++                              copy_m3_m4(trimat, ob->obmat);
++                              mat3_to_quat_is_ok(quat, trimat);
++                              
++                              return quat[array_index];
++                      }
++                      else if (strstr(identifier, "rotation_axis_angle")) {
++                              float axis[3], angle;
++                              
++                              mat4_to_axis_angle(axis, &angle, ob->obmat);
++                              
++                              /* w = 0, x,y,z = 1,2,3 */
++                              if (array_index == 0)
++                                      return angle;
++                              else
++                                      return axis[array_index - 1];
++                      }
                }
        }
        else if (ptr->type == &RNA_PoseBone) {
 -              Object *ob= (Object *)ptr->id.data; /* we assume that this is always set, and is an object */
++              Object *ob = (Object *)ptr->id.data; /* we assume that this is always set, and is an object */
                bPoseChannel *pchan= (bPoseChannel *)ptr->data;
--              bPoseChannel tchan;
++              float tmat[4][4];
                
--              /* make a copy of pchan so that we can apply and decompose its chan_mat, thus getting the 
--               * rest-pose to pose-mode transform that got stored there at the end of posing calculations
--               * for B-Bone deforms to use
--               *      - it should be safe to just make a local copy like this, since we're not doing anything with the copied pointers
++              /* Although it is not strictly required for this particular space conversion, 
++               * arg1 must not be null, as there is a null check for the other conversions to
++               * be safe. Therefore, the active object is passed here, and in many cases, this
++               * will be what owns the pose-channel that is getting this anyway.
                 */
--              memcpy(&tchan, pchan, sizeof(bPoseChannel));
-               pchan_apply_mat4(&tchan, pchan->chan_mat, TRUE);
 -              pchan_apply_mat4(&tchan, pchan->chan_mat);
++              copy_m4_m4(tmat, pchan->pose_mat);
++              constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
                
                /* Loc, Rot/Quat keyframes are supported... */
                if (strstr(identifier, "location")) {
                        /* only use for non-connected bones */
                        if ((pchan->bone->parent) && !(pchan->bone->flag & BONE_CONNECTED))
--                              return tchan.loc[array_index];
++                              return tmat[3][array_index];
                        else if (pchan->bone->parent == NULL)
--                              return tchan.loc[array_index];
++                              return tmat[3][array_index];
                }
                else if (strstr(identifier, "rotation_euler")) {
--                      return tchan.eul[array_index];
++                      float eul[3];
++                      
++                      mat4_to_eulO(eul, pchan->rotmode, tmat);
++                      return eul[array_index];
                }
                else if (strstr(identifier, "rotation_quaternion")) {
--                      return tchan.quat[array_index];
++                      float trimat[3][3], quat[4];
++                      
++                      copy_m3_m4(trimat, tmat);
++                      mat3_to_quat_is_ok(quat, trimat);
++                      
++                      return quat[array_index];
                }
--              else if (strstr(identifier, "rotation_axisangle")) {
++              else if (strstr(identifier, "rotation_axis_angle")) {
++                      float axis[3], angle;
++                      
++                      mat4_to_axis_angle(axis, &angle, tmat);
++                      
                        /* w = 0, x,y,z = 1,2,3 */
                        if (array_index == 0)
--                              return tchan.rotAngle;
++                              return angle;
                        else
--                              return tchan.rotAxis[array_index - 1];
++                              return axis[array_index - 1];
                }
        }