From 3d72c37f7ad3bf36ae36bc9860a9b0de16bd60ea Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 4 Nov 2022 13:06:53 +1100 Subject: 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 --- source/blender/blenkernel/BKE_object.h | 10 ++++++++++ source/blender/blenkernel/intern/object.cc | 22 ++++++++++++++++++++++ .../blender/editors/space_view3d/view3d_select.cc | 16 +++++++++++++--- 3 files changed, 45 insertions(+), 3 deletions(-) (limited to 'source') 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(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. -- cgit v1.2.3 From c5dde1c345438d48a83c984514c735ab89548ac5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 4 Nov 2022 13:59:03 +1100 Subject: Cleanup: quiet unused argument warning --- source/blender/render/intern/pipeline.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source') diff --git a/source/blender/render/intern/pipeline.cc b/source/blender/render/intern/pipeline.cc index e71ad1e26c1..1971c6fe6be 100644 --- a/source/blender/render/intern/pipeline.cc +++ b/source/blender/render/intern/pipeline.cc @@ -710,7 +710,7 @@ void render_copy_renderdata(RenderData *to, RenderData *from) void RE_InitState(Render *re, Render *source, RenderData *rd, - ListBase *render_layers, + ListBase * /*render_layers*/, ViewLayer *single_layer, int winx, int winy, -- cgit v1.2.3