Fix #140210: Edit Bone selection cycling wrong for active but unselected

Unlike object or posemode (where items not only need to be active but
also selected to be treated as a starting point for cycling through to
the next item behind it on the next click), armature editmode would
treat active (but unselected) bones as a starting point as well. Leading
to confusion if you just clear your selection prior.

For reference to the expected behavior, look at these comments in
`mouse_select_eval_buffer`

>/* Only exclude active object when it is selected. */

>/* When the active object is unselected or not in `buffer`, use the
nearest. */

Now for editbones, the way `get_nearest_editbonepoint` works, there were
actually two things preventing stuff from happening as expected:
- [1] we would still get "use_cycle" behavior if we have an unselected
(active) bone -> this is now checked for by looking at active bone
selection flags (NOTE: tip/root needs to be looked at as well). These
checks were once there, bd59781c66 removed them though.
- [2] without "use_cycle" behavior, we are still looping all hit bones
and there could be the situation where we could accept a first bone (in
the `bias > bias_max` condition -- that one could be the closest already
but does not set the `min_depth`), but continue to loop (now entering
the "bias == bias_max && do_nearest" condition and `min_depth` could
still be at INT_MAX) and accept a bone that is actually further away...
That logic is from 328ec2b172

Both points have now been addressed.

Pull Request: https://projects.blender.org/blender/blender/pulls/140348
This commit is contained in:
Philipp Oeser
2025-06-17 12:05:19 +02:00
committed by Philipp Oeser
parent 064d3a5730
commit 3ddd2dff37

View File

@@ -657,10 +657,14 @@ static EditBone *get_nearest_editbonepoint(
result_bias.base = nullptr;
result_bias.ebone = nullptr;
/* find the bone after the current active bone, so as to bump up its chances in selection.
* this way overlapping bones will cycle selection state as with objects. */
/* Find the bone after the current (selected) active bone, so as to bump up its chances in
* selection. this way overlapping bones will cycle selection state as with objects. */
Object *obedit_orig = vc->obedit;
EditBone *ebone_active_orig = static_cast<bArmature *>(obedit_orig->data)->act_edbone;
if ((ebone_active_orig->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) == 0) {
ebone_active_orig = nullptr;
}
if (ebone_active_orig == nullptr) {
use_cycle = false;
}
@@ -816,6 +820,7 @@ cache_end:
if (bias > bias_max) {
bias_max = bias;
min_depth = hit_result.depth;
result_bias.select_id = select_id;
result_bias.base = base;
result_bias.ebone = ebone;