Fix #123963: Unable to select through unselectable bones

When trying to select bones that are inside other bones which are not selectable,
the selection would fail. This is inconsistent with object mode, where unselectable
things are just ignored.
This patch fixes it for pose mode and edit mode.
Note that there are two areas for edit mode that were modified.
The one in `ed_armature_pick_bone_from_selectbuffer/202` is never actually reached,
but I added the code there for completeness.

The code in `get_nearest_editbonepoint` had to be modified some more to
implement a similar logic as `armature_select.cc/220`

Pull Request: https://projects.blender.org/blender/blender/pulls/129120
This commit is contained in:
Christoph Lendenfeld
2024-10-17 12:13:35 +02:00
committed by Christoph Lendenfeld
parent 40e1bf214a
commit 328ec2b172

View File

@@ -180,6 +180,9 @@ static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode
if (is_editmode == false) {
base = ED_armature_base_and_pchan_from_select_buffer(bases, hit_id, &pchan);
if (pchan != nullptr) {
if (pchan->bone->flag & BONE_UNSELECTABLE) {
continue;
}
if (findunsel) {
sel = (pchan->bone->flag & BONE_SELECTED);
}
@@ -196,6 +199,9 @@ static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode
}
else {
base = ED_armature_base_and_ebone_from_select_buffer(bases, hit_id, &ebone);
if (ebone->flag & BONE_UNSELECTABLE) {
continue;
}
if (findunsel) {
sel = (ebone->flag & BONE_SELECTED);
}
@@ -673,14 +679,15 @@ static EditBone *get_nearest_editbonepoint(
view3d_opengl_select_cache_begin();
{
const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL);
const eV3DSelectObjectFilter select_filter = VIEW3D_SELECT_FILTER_NOP;
GPUSelectStorage &storage = buffer.storage;
rcti rect;
BLI_rcti_init_pt_radius(&rect, vc->mval, 12);
/* VIEW3D_SELECT_PICK_ALL needs to be used or unselectable bones can block selectability of
* bones further back. See #123963. */
const int hits12 = view3d_opengl_select_with_id_filter(
vc, &buffer, &rect, eV3DSelectMode(select_mode), select_filter, select_id_ignore);
vc, &buffer, &rect, VIEW3D_SELECT_PICK_ALL, select_filter, select_id_ignore);
if (hits12 == 1) {
hits = selectbuffer_ret_hits_12(storage.as_mutable_span(), hits12);
@@ -689,7 +696,7 @@ static EditBone *get_nearest_editbonepoint(
else if (hits12 > 0) {
BLI_rcti_init_pt_radius(&rect, vc->mval, 5);
const int hits5 = view3d_opengl_select_with_id_filter(
vc, &buffer, &rect, eV3DSelectMode(select_mode), select_filter, select_id_ignore);
vc, &buffer, &rect, VIEW3D_SELECT_PICK_ALL, select_filter, select_id_ignore);
if (hits5 == 1) {
hits = selectbuffer_ret_hits_5(storage.as_mutable_span(), hits12, hits5);
@@ -754,8 +761,10 @@ cache_end:
cycle_order.best.as_u32 = 0;
}
int min_depth = INT_MAX;
for (int i = 0; i < hits; i++) {
const uint hitresult = buffer.storage[i].id;
const GPUSelectResult &result = buffer.storage[i];
const uint hitresult = result.id;
Base *base = nullptr;
EditBone *ebone;
@@ -763,6 +772,10 @@ cache_end:
/* If this fails, selection code is setting the selection ID's incorrectly. */
BLI_assert(base && ebone);
if (ebone->flag & BONE_UNSELECTABLE) {
continue;
}
/* Prioritized selection. */
{
int bias;
@@ -806,6 +819,14 @@ cache_end:
result_bias.base = base;
result_bias.ebone = ebone;
}
else if (bias == bias_max && do_nearest) {
if (min_depth > result.depth) {
min_depth = result.depth;
result_bias.hitresult = hitresult;
result_bias.base = base;
result_bias.ebone = ebone;
}
}
}
/* Cycle selected items (objects & bones). */