Pose paste: avoid auto-keying on unselected bones when 'selection only' is enabled

The `pose_bone_do_paste()` function is documented to only return a
non-NULL pointer on a successful paste, and the one caller that checks
the return value is expecting this behaviour. However, before this
commit, when a valid pose channel was found, 'Selected Only' was
enabled, and the bone was not selected, the function would still return
non-NULL. This resulted in auto-keying pose channels that were not
pasted.

Reviewed by: angavrilov

Differential Revision: https://developer.blender.org/D5891
This commit is contained in:
Sybren A. Stüvel
2019-09-25 15:07:57 +02:00
parent 2507b6a489
commit 1ca5c8491d

View File

@@ -543,16 +543,14 @@ static void set_pose_keys(Object *ob)
* \param chan: Bone that pose to paste comes from
* \param selOnly: Only paste on selected bones
* \param flip: Flip on x-axis
* \return Whether the bone that we pasted to if we succeeded
* \return The channel of the bone that was pasted to, or NULL if no paste was performed.
*/
static bPoseChannel *pose_bone_do_paste(Object *ob,
bPoseChannel *chan,
const bool selOnly,
const bool flip)
{
bPoseChannel *pchan;
char name[MAXBONENAME];
short paste_ok;
/* get the name - if flipping, we must flip this first */
if (flip) {
@@ -567,131 +565,126 @@ static bPoseChannel *pose_bone_do_paste(Object *ob,
* 2) if selection-masking is on, channel is selected -
* only selected bones get pasted on, allowing making both sides symmetrical.
*/
pchan = BKE_pose_channel_find_name(ob->pose, name);
if (selOnly) {
paste_ok = ((pchan) && (pchan->bone->flag & BONE_SELECTED));
bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, name);
if (pchan == NULL) {
return NULL;
}
else {
paste_ok = (pchan != NULL);
if (selOnly && (pchan->bone->flag & BONE_SELECTED) == 0) {
return NULL;
}
/* continue? */
if (paste_ok) {
/* only loc rot size
* - only copies transform info for the pose
*/
copy_v3_v3(pchan->loc, chan->loc);
copy_v3_v3(pchan->size, chan->size);
pchan->flag = chan->flag;
/* only loc rot size
* - only copies transform info for the pose
*/
copy_v3_v3(pchan->loc, chan->loc);
copy_v3_v3(pchan->size, chan->size);
pchan->flag = chan->flag;
/* check if rotation modes are compatible (i.e. do they need any conversions) */
if (pchan->rotmode == chan->rotmode) {
/* copy the type of rotation in use */
if (pchan->rotmode > 0) {
copy_v3_v3(pchan->eul, chan->eul);
}
else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
copy_v3_v3(pchan->rotAxis, chan->rotAxis);
pchan->rotAngle = chan->rotAngle;
}
else {
copy_qt_qt(pchan->quat, chan->quat);
}
}
else if (pchan->rotmode > 0) {
/* quat/axis-angle to euler */
if (chan->rotmode == ROT_MODE_AXISANGLE) {
axis_angle_to_eulO(pchan->eul, pchan->rotmode, chan->rotAxis, chan->rotAngle);
}
else {
quat_to_eulO(pchan->eul, pchan->rotmode, chan->quat);
}
/* check if rotation modes are compatible (i.e. do they need any conversions) */
if (pchan->rotmode == chan->rotmode) {
/* copy the type of rotation in use */
if (pchan->rotmode > 0) {
copy_v3_v3(pchan->eul, chan->eul);
}
else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
/* quat/euler to axis angle */
if (chan->rotmode > 0) {
eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->eul, chan->rotmode);
}
else {
quat_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->quat);
}
copy_v3_v3(pchan->rotAxis, chan->rotAxis);
pchan->rotAngle = chan->rotAngle;
}
else {
/* euler/axis-angle to quat */
if (chan->rotmode > 0) {
eulO_to_quat(pchan->quat, chan->eul, chan->rotmode);
}
else {
axis_angle_to_quat(pchan->quat, chan->rotAxis, pchan->rotAngle);
}
copy_qt_qt(pchan->quat, chan->quat);
}
/* B-Bone posing options should also be included... */
pchan->curve_in_x = chan->curve_in_x;
pchan->curve_in_y = chan->curve_in_y;
pchan->curve_out_x = chan->curve_out_x;
pchan->curve_out_y = chan->curve_out_y;
pchan->roll1 = chan->roll1;
pchan->roll2 = chan->roll2;
pchan->ease1 = chan->ease1;
pchan->ease2 = chan->ease2;
pchan->scale_in_x = chan->scale_in_x;
pchan->scale_in_y = chan->scale_in_y;
pchan->scale_out_x = chan->scale_out_x;
pchan->scale_out_y = chan->scale_out_y;
/* paste flipped pose? */
if (flip) {
pchan->loc[0] *= -1;
pchan->curve_in_x *= -1;
pchan->curve_out_x *= -1;
pchan->roll1 *= -1; // XXX?
pchan->roll2 *= -1; // XXX?
/* has to be done as eulers... */
if (pchan->rotmode > 0) {
pchan->eul[1] *= -1;
pchan->eul[2] *= -1;
}
else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
float eul[3];
axis_angle_to_eulO(eul, EULER_ORDER_DEFAULT, pchan->rotAxis, pchan->rotAngle);
eul[1] *= -1;
eul[2] *= -1;
eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, eul, EULER_ORDER_DEFAULT);
}
else {
float eul[3];
normalize_qt(pchan->quat);
quat_to_eul(eul, pchan->quat);
eul[1] *= -1;
eul[2] *= -1;
eul_to_quat(pchan->quat, eul);
}
}
else if (pchan->rotmode > 0) {
/* quat/axis-angle to euler */
if (chan->rotmode == ROT_MODE_AXISANGLE) {
axis_angle_to_eulO(pchan->eul, pchan->rotmode, chan->rotAxis, chan->rotAngle);
}
/* ID properties */
if (chan->prop) {
if (pchan->prop) {
/* if we have existing properties on a bone, just copy over the values of
* matching properties (i.e. ones which will have some impact) on to the
* target instead of just blinding replacing all [
*/
IDP_SyncGroupValues(pchan->prop, chan->prop);
}
else {
/* no existing properties, so assume that we want copies too? */
pchan->prop = IDP_CopyProperty(chan->prop);
}
else {
quat_to_eulO(pchan->eul, pchan->rotmode, chan->quat);
}
}
else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
/* quat/euler to axis angle */
if (chan->rotmode > 0) {
eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->eul, chan->rotmode);
}
else {
quat_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->quat);
}
}
else {
/* euler/axis-angle to quat */
if (chan->rotmode > 0) {
eulO_to_quat(pchan->quat, chan->eul, chan->rotmode);
}
else {
axis_angle_to_quat(pchan->quat, chan->rotAxis, pchan->rotAngle);
}
}
/* B-Bone posing options should also be included... */
pchan->curve_in_x = chan->curve_in_x;
pchan->curve_in_y = chan->curve_in_y;
pchan->curve_out_x = chan->curve_out_x;
pchan->curve_out_y = chan->curve_out_y;
pchan->roll1 = chan->roll1;
pchan->roll2 = chan->roll2;
pchan->ease1 = chan->ease1;
pchan->ease2 = chan->ease2;
pchan->scale_in_x = chan->scale_in_x;
pchan->scale_in_y = chan->scale_in_y;
pchan->scale_out_x = chan->scale_out_x;
pchan->scale_out_y = chan->scale_out_y;
/* paste flipped pose? */
if (flip) {
pchan->loc[0] *= -1;
pchan->curve_in_x *= -1;
pchan->curve_out_x *= -1;
pchan->roll1 *= -1; // XXX?
pchan->roll2 *= -1; // XXX?
/* has to be done as eulers... */
if (pchan->rotmode > 0) {
pchan->eul[1] *= -1;
pchan->eul[2] *= -1;
}
else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
float eul[3];
axis_angle_to_eulO(eul, EULER_ORDER_DEFAULT, pchan->rotAxis, pchan->rotAngle);
eul[1] *= -1;
eul[2] *= -1;
eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, eul, EULER_ORDER_DEFAULT);
}
else {
float eul[3];
normalize_qt(pchan->quat);
quat_to_eul(eul, pchan->quat);
eul[1] *= -1;
eul[2] *= -1;
eul_to_quat(pchan->quat, eul);
}
}
/* ID properties */
if (chan->prop) {
if (pchan->prop) {
/* if we have existing properties on a bone, just copy over the values of
* matching properties (i.e. ones which will have some impact) on to the
* target instead of just blinding replacing all [
*/
IDP_SyncGroupValues(pchan->prop, chan->prop);
}
else {
/* no existing properties, so assume that we want copies too? */
pchan->prop = IDP_CopyProperty(chan->prop);
}
}
/* return whether paste went ahead */
return pchan;
}