Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Parborg <darkdefende@gmail.com>2021-04-08 18:21:01 +0300
committerSebastian Parborg <darkdefende@gmail.com>2021-04-08 18:26:33 +0300
commit5e77ff79ccdaffb2df4d54c97f17359c017c9b85 (patch)
tree187207537fe318dd45cfbf7a42ab7be513536dbf /source/blender/editors/armature
parent5c4d24e1fd752a8a89d44d05e8e3f9b31f2d7db0 (diff)
Add ability to get a selection list of bones
This adds the ability to get a selection list for both edit mode bones and pose mode bones. To do this the selection menu list logic had to be reworked a bit. Before it only stored the names of objects. This might work will of objects, however as stated in the code, it might fail for linked objects (so multiple object can have the same name in some corner cases). For bones it is a very common occurance where you can have multiple armature that has the same bone names. So now it also stores the object and bone pointers for this case. Reviewed By: Sybren Differential Revision: http://developer.blender.org/D10570 Fix T85796
Diffstat (limited to 'source/blender/editors/armature')
-rw-r--r--source/blender/editors/armature/armature_select.c204
-rw-r--r--source/blender/editors/armature/pose_select.c186
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;
}