[Bf-blender-cvs] [3d72c37f7ad] blender-v3.4-release: Fix T101686: WPaint + Pose select fails with GPU depth-picking disabled

Campbell Barton noreply at git.blender.org
Fri Nov 4 03:59:57 CET 2022


Commit: 3d72c37f7ad3bf36ae36bc9860a9b0de16bd60ea
Author: Campbell Barton
Date:   Fri Nov 4 13:06:53 2022 +1100
Branches: blender-v3.4-release
https://developer.blender.org/rB3d72c37f7ad3bf36ae36bc9860a9b0de16bd60ea

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]: b1908f2e0b23988627772f6a6d968d8351dca6d7

===================================================================

M	source/blender/blenkernel/BKE_object.h
M	source/blender/blenkernel/intern/object.cc
M	source/blender/editors/space_view3d/view3d_select.cc

===================================================================

diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 5cbd7937f3f..cfad8c5cfdb 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -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,
diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc
index 6d1b7caeea6..9085a54d86f 100644
--- a/source/blender/blenkernel/intern/object.cc
+++ b/source/blender/blenkernel/intern/object.cc
@@ -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,
diff --git a/source/blender/editors/space_view3d/view3d_select.cc b/source/blender/editors/space_view3d/view3d_select.cc
index 9c450e85d23..a7be569894d 100644
--- a/source/blender/editors/space_view3d/view3d_select.cc
+++ b/source/blender/editors/space_view3d/view3d_select.cc
@@ -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.



More information about the Bf-blender-cvs mailing list