diff options
Diffstat (limited to 'source/blender/editors/armature')
-rw-r--r-- | source/blender/editors/armature/armature_select.c | 204 | ||||
-rw-r--r-- | source/blender/editors/armature/pose_select.c | 186 |
2 files changed, 210 insertions, 180 deletions
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index 226253cc063..9b598872d8b 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -961,131 +961,145 @@ bool ED_armature_edit_deselect_all_visible_multi(bContext *C) /** \name Select Cursor Pick API * \{ */ -/* context: editmode armature in view3d */ -bool ED_armature_edit_select_pick( - bContext *C, const int mval[2], bool extend, bool deselect, bool toggle) +bool ED_armature_edit_select_pick_bone(bContext *C, + Base *basact, + EditBone *ebone, + const int selmask, + const bool extend, + const bool deselect, + const bool toggle) { - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - ViewContext vc; - EditBone *nearBone = NULL; - int selmask; - Base *basact = NULL; + if (!ebone) { + return false; + } - ED_view3d_viewcontext_init(C, &vc, depsgraph); - vc.mval[0] = mval[0]; - vc.mval[1] = mval[1]; + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); - nearBone = get_nearest_editbonepoint(&vc, true, true, &basact, &selmask); - if (nearBone) { - ED_view3d_viewcontext_init_object(&vc, basact->object); - bArmature *arm = vc.obedit->data; + BLI_assert(BKE_object_is_in_editmode(basact->object)); + bArmature *arm = basact->object->data; - if (!EBONE_SELECTABLE(arm, nearBone)) { - return false; - } + if (!EBONE_SELECTABLE(arm, ebone)) { + return false; + } - if (!extend && !deselect && !toggle) { - uint bases_len = 0; - Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( - vc.view_layer, vc.v3d, &bases_len); - ED_armature_edit_deselect_all_multi_ex(bases, bases_len); - MEM_freeN(bases); - } + if (!extend && !deselect && !toggle) { + uint bases_len = 0; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( + view_layer, v3d, &bases_len); + ED_armature_edit_deselect_all_multi_ex(bases, bases_len); + MEM_freeN(bases); + } - /* by definition the non-root connected bones have no root point drawn, - * so a root selection needs to be delivered to the parent tip */ + /* By definition the non-root connected bones have no root point drawn, + * so a root selection needs to be delivered to the parent tip. */ - if (selmask & BONE_SELECTED) { - if (nearBone->parent && (nearBone->flag & BONE_CONNECTED)) { - /* click in a chain */ - if (extend) { - /* select this bone */ - nearBone->flag |= BONE_TIPSEL; - nearBone->parent->flag |= BONE_TIPSEL; - } - else if (deselect) { - /* deselect this bone */ - nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED); - /* only deselect parent tip if it is not selected */ - if (!(nearBone->parent->flag & BONE_SELECTED)) { - nearBone->parent->flag &= ~BONE_TIPSEL; - } + if (selmask & BONE_SELECTED) { + if (ebone->parent && (ebone->flag & BONE_CONNECTED)) { + /* Bone is in a chain. */ + if (extend) { + /* Select this bone. */ + ebone->flag |= BONE_TIPSEL; + ebone->parent->flag |= BONE_TIPSEL; + } + else if (deselect) { + /* Deselect this bone. */ + ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED); + /* Only deselect parent tip if it is not selected. */ + if (!(ebone->parent->flag & BONE_SELECTED)) { + ebone->parent->flag &= ~BONE_TIPSEL; } - else if (toggle) { - /* hold shift inverts this bone's selection */ - if (nearBone->flag & BONE_SELECTED) { - /* deselect this bone */ - nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED); - /* only deselect parent tip if it is not selected */ - if (!(nearBone->parent->flag & BONE_SELECTED)) { - nearBone->parent->flag &= ~BONE_TIPSEL; - } - } - else { - /* select this bone */ - nearBone->flag |= BONE_TIPSEL; - nearBone->parent->flag |= BONE_TIPSEL; + } + else if (toggle) { + /* Toggle inverts this bone's selection. */ + if (ebone->flag & BONE_SELECTED) { + /* Deselect this bone. */ + ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED); + /* Only deselect parent tip if it is not selected. */ + if (!(ebone->parent->flag & BONE_SELECTED)) { + ebone->parent->flag &= ~BONE_TIPSEL; } } else { - /* select this bone */ - nearBone->flag |= BONE_TIPSEL; - nearBone->parent->flag |= BONE_TIPSEL; + /* Select this bone. */ + ebone->flag |= BONE_TIPSEL; + ebone->parent->flag |= BONE_TIPSEL; } } else { - if (extend) { - nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL); - } - else if (deselect) { - nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL); - } - else if (toggle) { - /* hold shift inverts this bone's selection */ - if (nearBone->flag & BONE_SELECTED) { - nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL); - } - else { - nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL); - } - } - else { - nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL); - } + /* Select this bone. */ + ebone->flag |= BONE_TIPSEL; + ebone->parent->flag |= BONE_TIPSEL; } } else { if (extend) { - nearBone->flag |= selmask; + ebone->flag |= (BONE_TIPSEL | BONE_ROOTSEL); } else if (deselect) { - nearBone->flag &= ~selmask; + ebone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL); } - else if (toggle && (nearBone->flag & selmask)) { - nearBone->flag &= ~selmask; + else if (toggle) { + /* Toggle inverts this bone's selection. */ + if (ebone->flag & BONE_SELECTED) { + ebone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL); + } + else { + ebone->flag |= (BONE_TIPSEL | BONE_ROOTSEL); + } } else { - nearBone->flag |= selmask; + ebone->flag |= (BONE_TIPSEL | BONE_ROOTSEL); } } - - ED_armature_edit_sync_selection(arm->edbo); - - /* then now check for active status */ - if (ED_armature_ebone_selectflag_get(nearBone)) { - arm->act_edbone = nearBone; + } + else { + if (extend) { + ebone->flag |= selmask; } - - if (vc.view_layer->basact != basact) { - ED_object_base_activate(C, basact); + else if (deselect) { + ebone->flag &= ~selmask; + } + else if (toggle && (ebone->flag & selmask)) { + ebone->flag &= ~selmask; } + else { + ebone->flag |= selmask; + } + } - WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object); - DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE); - return true; + ED_armature_edit_sync_selection(arm->edbo); + + /* Then now check for active status. */ + if (ED_armature_ebone_selectflag_get(ebone)) { + arm->act_edbone = ebone; + } + + if (view_layer->basact != basact) { + ED_object_base_activate(C, basact); } - return false; + WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object); + DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE); + return true; +} + +/* context: editmode armature in view3d */ +bool ED_armature_edit_select_pick( + bContext *C, const int mval[2], bool extend, bool deselect, bool toggle) +{ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + ViewContext vc; + EditBone *nearBone = NULL; + int selmask; + Base *basact = NULL; + + ED_view3d_viewcontext_init(C, &vc, depsgraph); + vc.mval[0] = mval[0]; + vc.mval[1] = mval[1]; + + nearBone = get_nearest_editbonepoint(&vc, true, true, &basact, &selmask); + return ED_armature_edit_select_pick_bone(C, basact, nearBone, selmask, extend, deselect, toggle); } /** \} */ diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index a3f97000509..0b0f1925746 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -138,6 +138,106 @@ void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select) } } +void ED_armature_pose_select_pick_bone(ViewLayer *view_layer, + View3D *v3d, + Object *ob, + Bone *bone, + const bool extend, + const bool deselect, + const bool toggle) +{ + 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; + + /* Since we do unified select, we don't shift+select a bone if the + * armature object was not active yet. + * Note, 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 - campbell */ + 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 (!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); + } + } + } + FOREACH_VISIBLE_BASE_END; + } + bone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + arm->act_bone = bone; + } + 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); + } + else if (toggle) { + 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); + arm->act_bone = bone; + } + } + } + + 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] + */ + 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); + } +} + /** * Called for mode-less pose selection. * assumes the active object is still on old situation. @@ -159,96 +259,12 @@ bool ED_armature_pose_select_pick_with_buffer(ViewLayer *view_layer, return 0; } - Object *ob_act = OBACT(view_layer); - BLI_assert(OBEDIT_FROM_VIEW_LAYER(view_layer) == NULL); - /* Callers happen to already get the active base */ Base *base_dummy = NULL; nearBone = ED_armature_pick_bone_from_selectbuffer( &base, 1, buffer, hits, 1, do_nearest, &base_dummy); - /* if the bone cannot be affected, don't do anything */ - if ((nearBone) && !(nearBone->flag & BONE_UNSELECTABLE)) { - 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, 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 - campbell */ - 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 below */ - nearBone->flag &= ~BONE_SELECTED; - } - } - - 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); - } - } - } - FOREACH_VISIBLE_BASE_END; - } - nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - arm->act_bone = nearBone; - } - else { - if (extend) { - nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - arm->act_bone = nearBone; - } - else if (deselect) { - nearBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - } - else if (toggle) { - if (nearBone->flag & BONE_SELECTED) { - /* if not active, we make it active */ - if (nearBone != arm->act_bone) { - arm->act_bone = nearBone; - } - else { - nearBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - } - } - else { - nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - arm->act_bone = nearBone; - } - } - } - - if (ob_act) { - /* in weightpaint we select the associated vertex group too */ - if (ob_act->mode & OB_MODE_ALL_WEIGHT_PAINT) { - if (nearBone == arm->act_bone) { - ED_vgroup_select_by_name(ob_act, nearBone->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] - */ - 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); - } - } + ED_armature_pose_select_pick_bone(view_layer, v3d, ob, nearBone, extend, deselect, toggle); return nearBone != NULL; } |