Fix T101686: WPaint + Pose select fails with GPU depth-picking disabled

Regression in [0], however the primary purpose of that code was to
cycle away from the active object (behavior which was intentionally
removed, see: T96752).

This broke weight-paint + pose-selection (Ctrl-LMB)
when the GPU depth picking preference was disabled.
Causing selection to pick the mesh object instead of the pose bones.
This de-selected the armature, making the pose bones unselectable
instead of selecting the pose bone as intended.

Adding the old code back (restricting it to weight-paint mode)
fixes the bug but reintroduces fairly involved logic unnecessarily.

Instead, prioritize bone selecting when in weight-paint & pose mode
(previously this was only done in pose-mode).

[0]: b1908f2e0b
This commit is contained in:
Campbell Barton 2022-11-04 13:06:53 +11:00
parent 1452b44352
commit 3d72c37f7a
Notes: blender-bot 2023-02-14 11:00:17 +01:00
Referenced by issue #101686, Regression: Weight Painting: CTRL+LClick to select bone does not work if mesh is in front of bone
3 changed files with 45 additions and 3 deletions

View File

@ -283,7 +283,17 @@ void BKE_object_apply_parent_inverse(struct Object *ob);
void BKE_object_matrix_local_get(struct Object *ob, float r_mat[4][4]);
bool BKE_object_pose_context_check(const struct Object *ob);
struct Object *BKE_object_pose_armature_get(struct Object *ob);
/**
* A version of #BKE_object_pose_armature_get with an additional check.
* When `ob` isn't an armature: only return the referenced pose object
* when the active object is in weight paint mode.
*
* \note Some callers need to check that pose bones are selectable
* which isn't the case when the object using the armature isn't in weight-paint mode.
*/
struct Object *BKE_object_pose_armature_get_with_wpaint_check(struct Object *ob);
struct Object *BKE_object_pose_armature_get_visible(struct Object *ob,
const struct Scene *scene,
struct ViewLayer *view_layer,

View File

@ -2541,6 +2541,28 @@ Object *BKE_object_pose_armature_get(Object *ob)
return nullptr;
}
Object *BKE_object_pose_armature_get_with_wpaint_check(Object *ob)
{
/* When not in weight paint mode. */
if (ob) {
switch (ob->type) {
case OB_MESH: {
if ((ob->mode & OB_MODE_WEIGHT_PAINT) == 0) {
return nullptr;
}
break;
}
case OB_GPENCIL: {
if ((ob->mode & OB_MODE_WEIGHT_GPENCIL) == 0) {
return nullptr;
}
break;
}
}
}
return BKE_object_pose_armature_get(ob);
}
Object *BKE_object_pose_armature_get_visible(Object *ob,
const Scene *scene,
ViewLayer *view_layer,

View File

@ -2616,6 +2616,12 @@ static bool ed_object_select_pick(bContext *C,
Base *basact = nullptr;
const eObjectMode object_mode = oldbasact ? static_cast<eObjectMode>(oldbasact->object->mode) :
OB_MODE_OBJECT;
/* For the most part this is equivalent to `(object_mode & OB_MODE_POSE) != 0`
* however this logic should also run with weight-paint + pose selection.
* Without this, selection in weight-paint mode can de-select armatures which isn't useful,
* see: T101686. */
const bool has_pose_old = (oldbasact &&
BKE_object_pose_armature_get_with_wpaint_check(oldbasact->object));
/* When enabled, don't attempt any further selection. */
bool handled = false;
@ -2654,7 +2660,7 @@ static bool ed_object_select_pick(bContext *C,
*
* This way prioritizing based on pose-mode has a bias to stay in pose-mode
* without having to enforce this through locking the object mode. */
bool do_bones_get_priotity = (object_mode & OB_MODE_POSE) != 0;
bool do_bones_get_priotity = has_pose_old;
basact = (gpu->hits > 0) ? mouse_select_eval_buffer(&vc,
gpu->buffer,
@ -2666,10 +2672,14 @@ static bool ed_object_select_pick(bContext *C,
nullptr;
}
/* See comment for `has_pose_old`, the same rationale applies here. */
const bool has_pose_new = (basact &&
BKE_object_pose_armature_get_with_wpaint_check(basact->object));
/* Select pose-bones or camera-tracks. */
if (((gpu->hits > 0) && gpu->has_bones) ||
/* Special case, even when there are no hits, pose logic may de-select all bones. */
((gpu->hits == 0) && (object_mode & OB_MODE_POSE))) {
((gpu->hits == 0) && has_pose_old)) {
if (basact && (gpu->has_bones && (basact->object->type == OB_CAMERA))) {
MovieClip *clip = BKE_object_movieclip_get(scene, basact->object, false);
@ -2729,7 +2739,7 @@ static bool ed_object_select_pick(bContext *C,
handled = true;
}
else if ((object_mode & OB_MODE_POSE) && (basact->object->mode & OB_MODE_POSE)) {
else if (has_pose_old && has_pose_new) {
/* Within pose-mode, keep the current selection when switching pose bones,
* this is noticeable when in pose mode with multiple objects at once.
* Where selecting the bone of a different object would de-select this one.