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:
authorCampbell Barton <campbell@blender.org>2022-03-15 13:03:04 +0300
committerCampbell Barton <campbell@blender.org>2022-03-16 06:48:25 +0300
commit5e5285baf621a0c225cb5fc06fcec6ffed8302d7 (patch)
treefcdc655a6b063d32a7630b648e126c20ade295f2 /source/blender/editors/armature
parent9a763d24f2b50ad38d22cad0a23d7344afe5f1c7 (diff)
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.
Diffstat (limited to 'source/blender/editors/armature')
-rw-r--r--source/blender/editors/armature/armature_select.c223
-rw-r--r--source/blender/editors/armature/pose_select.c166
2 files changed, 224 insertions, 165 deletions
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index d7240782840..d1a5c128c35 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -951,127 +951,174 @@ 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)
+ const struct SelectPick_Params *params)
{
- if (!ebone) {
- return false;
- }
-
ViewLayer *view_layer = CTX_data_view_layer(C);
View3D *v3d = CTX_wm_view3d(C);
+ bool changed = false;
+ bool found = false;
- BLI_assert(BKE_object_is_in_editmode(basact->object));
- bArmature *arm = basact->object->data;
-
- if (!EBONE_SELECTABLE(arm, ebone)) {
- return false;
+ if (ebone) {
+ bArmature *arm = basact->object->data;
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ found = true;
+ }
}
- if (!extend && !deselect && !toggle) {
+ if ((params->sel_op == SEL_OP_SET) && (found || params->deselect_all)) {
+ /* Deselect everything. */
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);
+ changed = true;
}
- /* 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 (found) {
+ BLI_assert(BKE_object_is_in_editmode(basact->object));
+ bArmature *arm = basact->object->data;
- 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) {
- /* 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;
+ /* 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 (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+
+ /* Bone is in a chain. */
+ switch (params->sel_op) {
+ case SEL_OP_ADD: {
+ /* Select this bone. */
+ ebone->flag |= BONE_TIPSEL;
+ ebone->parent->flag |= BONE_TIPSEL;
+ break;
+ }
+ case SEL_OP_SUB: {
+ /* 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;
+ }
+ break;
+ }
+ case SEL_OP_XOR: {
+ /* 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. */
+ ebone->flag |= BONE_TIPSEL;
+ ebone->parent->flag |= BONE_TIPSEL;
+ }
+ break;
+ }
+ case SEL_OP_SET: {
+ /* Select this bone. */
+ ebone->flag |= BONE_TIPSEL;
+ ebone->parent->flag |= BONE_TIPSEL;
+ break;
+ }
+ case SEL_OP_AND: {
+ BLI_assert_unreachable(); /* Doesn't make sense for picking. */
+ break;
}
- }
- else {
- /* Select this bone. */
- ebone->flag |= BONE_TIPSEL;
- ebone->parent->flag |= BONE_TIPSEL;
}
}
else {
- /* Select this bone. */
- ebone->flag |= BONE_TIPSEL;
- ebone->parent->flag |= BONE_TIPSEL;
+ switch (params->sel_op) {
+ case SEL_OP_ADD: {
+ ebone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
+ break;
+ }
+ case SEL_OP_SUB: {
+ ebone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
+ break;
+ }
+ case SEL_OP_XOR: {
+ /* Toggle inverts this bone's selection. */
+ if (ebone->flag & BONE_SELECTED) {
+ ebone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else {
+ ebone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ break;
+ }
+ case SEL_OP_SET: {
+ ebone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
+ break;
+ }
+ case SEL_OP_AND: {
+ BLI_assert_unreachable(); /* Doesn't make sense for picking. */
+ break;
+ }
+ }
}
}
else {
- if (extend) {
- ebone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
- }
- else if (deselect) {
- ebone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
- }
- else if (toggle) {
- /* Toggle inverts this bone's selection. */
- if (ebone->flag & BONE_SELECTED) {
- ebone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
+ switch (params->sel_op) {
+ case SEL_OP_ADD: {
+ ebone->flag |= selmask;
+ break;
}
- else {
- ebone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
+ case SEL_OP_SUB: {
+ ebone->flag &= ~selmask;
+ break;
+ }
+ case SEL_OP_XOR: {
+ if (ebone->flag & selmask) {
+ ebone->flag &= ~selmask;
+ }
+ else {
+ ebone->flag |= selmask;
+ }
+ break;
+ }
+ case SEL_OP_SET: {
+ ebone->flag |= selmask;
+ break;
+ }
+ case SEL_OP_AND: {
+ BLI_assert_unreachable(); /* Doesn't make sense for picking. */
+ break;
}
- }
- else {
- ebone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
}
}
- }
- else {
- if (extend) {
- ebone->flag |= selmask;
- }
- else if (deselect) {
- ebone->flag &= ~selmask;
- }
- else if (toggle && (ebone->flag & selmask)) {
- ebone->flag &= ~selmask;
- }
- else {
- ebone->flag |= selmask;
+
+ ED_armature_edit_sync_selection(arm->edbo);
+
+ /* Then now check for active status. */
+ if (ED_armature_ebone_selectflag_get(ebone)) {
+ arm->act_edbone = ebone;
}
- }
- ED_armature_edit_sync_selection(arm->edbo);
+ if (view_layer->basact != basact) {
+ ED_object_base_activate(C, basact);
+ }
- /* Then now check for active status. */
- if (ED_armature_ebone_selectflag_get(ebone)) {
- arm->act_edbone = ebone;
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object);
+ DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
+ changed = true;
}
- if (view_layer->basact != basact) {
- ED_object_base_activate(C, basact);
+ if (changed) {
+ ED_outliner_select_sync_from_edit_bone_tag(C);
}
- 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;
+ return changed || found;
}
-bool ED_armature_edit_select_pick(
- bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
+bool ED_armature_edit_select_pick(bContext *C,
+ const int mval[2],
+ const struct SelectPick_Params *params)
+
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
@@ -1084,7 +1131,7 @@ bool ED_armature_edit_select_pick(
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);
+ return ED_armature_edit_select_pick_bone(C, basact, nearBone, selmask, params);
}
/** \} */
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)