From 5e5285baf621a0c225cb5fc06fcec6ffed8302d7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 15 Mar 2022 21:03:04 +1100 Subject: View 3D: move picking arguments into a struct & minor refactor - Add SelectPick_Params struct to make picking logic more straightforward and easier to extend. - Use `eSelectOp` instead of booleans (extend, deselect, toggle) which were used to represent 4 states (which wasn't obvious). - Handle deselect_all when pocking instead of view3d_select_exec, de-duplicate de-selection which was already needed in when replacing the selection in picking functions. - Handle outliner update & notifiers in the picking functions instead of view3d_select_exec. - Fix particle select deselect_all option which did nothing. --- source/blender/editors/armature/pose_select.c | 166 ++++++++++++++------------ 1 file changed, 89 insertions(+), 77 deletions(-) (limited to 'source/blender/editors/armature/pose_select.c') diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index 12238280b06..1cf56389580 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -121,104 +121,120 @@ void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select) } } -void ED_armature_pose_select_pick_bone(ViewLayer *view_layer, +bool ED_armature_pose_select_pick_bone(ViewLayer *view_layer, View3D *v3d, Object *ob, Bone *bone, - const bool extend, - const bool deselect, - const bool toggle) + const struct SelectPick_Params *params) { - if (!ob || !ob->pose) { - return; - } - - Object *ob_act = OBACT(view_layer); - BLI_assert(OBEDIT_FROM_VIEW_LAYER(view_layer) == NULL); - - /* If the bone cannot be affected, don't do anything. */ - if (bone == NULL || (bone->flag & BONE_UNSELECTABLE)) { - return; - } - bArmature *arm = ob->data; + bool found = false; + bool changed = false; - /* Since we do unified select, we don't shift+select a bone if the - * armature object was not active yet. - * NOTE(campbell): special exception for armature mode so we can do multi-select - * we could check for multi-select explicitly but think its fine to - * always give predictable behavior in weight paint mode. */ - if ((ob_act == NULL) || ((ob_act != ob) && (ob_act->mode & OB_MODE_ALL_WEIGHT_PAINT) == 0)) { - /* When we are entering into posemode via toggle-select, - * from another active object - always select the bone. */ - if (!extend && !deselect && toggle) { - /* Re-select the bone again later in this function. */ - bone->flag &= ~BONE_SELECTED; + if (ob || ob->pose) { + if (bone && ((bone->flag & BONE_UNSELECTABLE) == 0)) { + found = true; } } - if (!extend && !deselect && !toggle) { - { - /* Don't use 'BKE_object_pose_base_array_get_unique' - * because we may be selecting from object mode. */ - FOREACH_VISIBLE_BASE_BEGIN (view_layer, v3d, base_iter) { - Object *ob_iter = base_iter->object; - if ((ob_iter->type == OB_ARMATURE) && (ob_iter->mode & OB_MODE_POSE)) { - if (ED_pose_deselect_all(ob_iter, SEL_DESELECT, true)) { - ED_pose_bone_select_tag_update(ob_iter); - } + if ((params->sel_op == SEL_OP_SET) && (found || params->deselect_all)) { + /* Don't use 'BKE_object_pose_base_array_get_unique' + * because we may be selecting from object mode. */ + FOREACH_VISIBLE_BASE_BEGIN (view_layer, v3d, base_iter) { + Object *ob_iter = base_iter->object; + if ((ob_iter->type == OB_ARMATURE) && (ob_iter->mode & OB_MODE_POSE)) { + if (ED_pose_deselect_all(ob_iter, SEL_DESELECT, true)) { + ED_pose_bone_select_tag_update(ob_iter); } } - FOREACH_VISIBLE_BASE_END; } - bone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - arm->act_bone = bone; + FOREACH_VISIBLE_BASE_END; + changed = true; } - else { - if (extend) { - bone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - arm->act_bone = bone; - } - else if (deselect) { - bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + + if (found) { + Object *ob_act = OBACT(view_layer); + BLI_assert(OBEDIT_FROM_VIEW_LAYER(view_layer) == NULL); + + /* If the bone cannot be affected, don't do anything. */ + bArmature *arm = ob->data; + + /* Since we do unified select, we don't shift+select a bone if the + * armature object was not active yet. + * NOTE(campbell): special exception for armature mode so we can do multi-select + * we could check for multi-select explicitly but think its fine to + * always give predictable behavior in weight paint mode. */ + if ((ob_act == NULL) || ((ob_act != ob) && (ob_act->mode & OB_MODE_ALL_WEIGHT_PAINT) == 0)) { + /* When we are entering into posemode via toggle-select, + * from another active object - always select the bone. */ + if (params->sel_op == SEL_OP_SET) { + /* Re-select the bone again later in this function. */ + bone->flag &= ~BONE_SELECTED; + } } - else if (toggle) { - if (bone->flag & BONE_SELECTED) { - /* If not active, we make it active. */ - if (bone != arm->act_bone) { - arm->act_bone = bone; + + switch (params->sel_op) { + case SEL_OP_ADD: { + bone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + arm->act_bone = bone; + break; + } + case SEL_OP_SUB: { + bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + break; + } + case SEL_OP_XOR: { + if (bone->flag & BONE_SELECTED) { + /* If not active, we make it active. */ + if (bone != arm->act_bone) { + arm->act_bone = bone; + } + else { + bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + } } else { - bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + bone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + arm->act_bone = bone; } + break; } - else { + case SEL_OP_SET: { bone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); arm->act_bone = bone; + break; + } + case SEL_OP_AND: { + BLI_assert_unreachable(); /* Doesn't make sense for picking. */ + break; } } - } - if (ob_act) { - /* In weightpaint we select the associated vertex group too. */ - if (ob_act->mode & OB_MODE_ALL_WEIGHT_PAINT) { - if (bone == arm->act_bone) { - ED_vgroup_select_by_name(ob_act, bone->name); - DEG_id_tag_update(&ob_act->id, ID_RECALC_GEOMETRY); + if (ob_act) { + /* In weightpaint we select the associated vertex group too. */ + if (ob_act->mode & OB_MODE_ALL_WEIGHT_PAINT) { + if (bone == arm->act_bone) { + ED_vgroup_select_by_name(ob_act, bone->name); + DEG_id_tag_update(&ob_act->id, ID_RECALC_GEOMETRY); + } } - } - /* If there are some dependencies for visualizing armature state - * (e.g. Mask Modifier in 'Armature' mode), force update. - */ - else if (arm->flag & ARM_HAS_VIZ_DEPS) { - /* NOTE: ob not ob_act here is intentional - it's the source of the - * bones being selected [T37247] + /* If there are some dependencies for visualizing armature state + * (e.g. Mask Modifier in 'Armature' mode), force update. */ - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + else if (arm->flag & ARM_HAS_VIZ_DEPS) { + /* NOTE: ob not ob_act here is intentional - it's the source of the + * bones being selected [T37247] + */ + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + } + + /* Tag armature for copy-on-write update (since act_bone is in armature not object). */ + DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE); } - /* Tag armature for copy-on-write update (since act_bone is in armature not object). */ - DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE); + changed = true; } + + return changed || found; } bool ED_armature_pose_select_pick_with_buffer(ViewLayer *view_layer, @@ -226,9 +242,7 @@ bool ED_armature_pose_select_pick_with_buffer(ViewLayer *view_layer, Base *base, const struct GPUSelectResult *buffer, const short hits, - bool extend, - bool deselect, - bool toggle, + const struct SelectPick_Params *params, bool do_nearest) { Object *ob = base->object; @@ -243,9 +257,7 @@ bool ED_armature_pose_select_pick_with_buffer(ViewLayer *view_layer, nearBone = ED_armature_pick_bone_from_selectbuffer( &base, 1, buffer, hits, 1, do_nearest, &base_dummy); - ED_armature_pose_select_pick_bone(view_layer, v3d, ob, nearBone, extend, deselect, toggle); - - return nearBone != NULL; + return ED_armature_pose_select_pick_bone(view_layer, v3d, ob, nearBone, params); } void ED_armature_pose_select_in_wpaint_mode(ViewLayer *view_layer, Base *base_select) -- cgit v1.2.3