From c6c9e168e272a0fe31b9a6f8704adb067fb9f88f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 18 Jul 2019 18:45:56 +1000 Subject: Fix T58447: Unselected bone used for constraint target --- source/blender/blenkernel/BKE_action.h | 1 + source/blender/blenkernel/intern/action.c | 33 +++++++++++++++++++++++ source/blender/editors/object/object_constraint.c | 14 +++++++--- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 69f3070fcba..a4863780d2e 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -160,6 +160,7 @@ void BKE_pose_copy_data(struct bPose **dst, const struct bPose *src, const bool void BKE_pose_channel_copy_data(struct bPoseChannel *pchan, const struct bPoseChannel *pchan_from); struct bPoseChannel *BKE_pose_channel_find_name(const struct bPose *pose, const char *name); struct bPoseChannel *BKE_pose_channel_active(struct Object *ob); +struct bPoseChannel *BKE_pose_channel_active_or_first_selected(struct Object *ob); struct bPoseChannel *BKE_pose_channel_verify(struct bPose *pose, const char *name); struct bPoseChannel *BKE_pose_channel_get_mirrored(const struct bPose *pose, const char *name); diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 3e3a533275b..a7159f85dc2 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -43,6 +43,7 @@ #include "BLT_translation.h" #include "BKE_action.h" +#include "BKE_armature.h" #include "BKE_anim.h" #include "BKE_animsys.h" #include "BKE_constraint.h" @@ -524,6 +525,38 @@ bPoseChannel *BKE_pose_channel_active(Object *ob) return NULL; } +/** + * Use this when detecting the "other selected bone", + * when we have multiple armatures in pose mode. + * + * In this case the active-selected is an obvious choice when finding the target for a + * constraint for eg. however from the users perspective the active pose bone of the + * active object is the _real_ active bone, so any other non-active selected bone + * is a candidate for being the other selected bone, see: T58447. + */ +bPoseChannel *BKE_pose_channel_active_or_first_selected(struct Object *ob) +{ + bArmature *arm = (ob) ? ob->data : NULL; + + if (ELEM(NULL, ob, ob->pose, arm)) { + return NULL; + } + + bPoseChannel *pchan = BKE_pose_channel_active(ob); + if (pchan && (pchan->bone->flag & BONE_SELECTED) && PBONE_VISIBLE(arm, pchan->bone)) { + return pchan; + } + + for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { + if (pchan->bone != NULL) { + if ((pchan->bone->flag & BONE_SELECTED) && PBONE_VISIBLE(arm, pchan->bone)) { + return pchan; + } + } + } + return NULL; +} + /** * \see #ED_armature_ebone_get_mirrored (edit-mode, matching function) */ diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 9c23daab923..5ef133e87de 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -34,6 +34,7 @@ #include "BLT_translation.h" #include "DNA_anim_types.h" +#include "DNA_armature_types.h" #include "DNA_constraint_types.h" #include "DNA_curve_types.h" #include "DNA_scene_types.h" @@ -1815,10 +1816,15 @@ static bool get_new_constraint_target( */ if ((ob->type == OB_ARMATURE) && (ob->mode & OB_MODE_POSE) && (!only_curve && !only_mesh)) { - /* just use the active bone, and assume that it is visible + usable */ - *tar_ob = ob; - *tar_pchan = BKE_pose_channel_active(ob); - found = true; + + /* Only use the object & bone if the bone is visible & selected + * since we may have multiple objects in pose mode at once. */ + bPoseChannel *pchan = BKE_pose_channel_active_or_first_selected(ob); + if (pchan != NULL) { + *tar_pchan = pchan; + *tar_ob = ob; + found = true; + } break; } -- cgit v1.2.3