From 40f8ddf8297a062968fc6a1523aa210d69c22626 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 26 Mar 2019 18:47:55 +1100 Subject: 3D View: move deselect all logic into an option This removes `VIEW3D_OT_select_or_deselect_all`, adding a deselect_all option to the `VIEW3D_OT_select` operator. - Add utility functions to simplify de-selecting all. - Return true from selection functions when they change the selection to avoid redundant updates. - Use arrays of bases when passing objects between selection utility functions since some users require bases. - Fix logical error in box selection that updated all objects after the first hit. --- source/blender/blenkernel/BKE_mball.h | 17 +- source/blender/blenkernel/intern/mball.c | 67 +-- source/blender/editors/armature/armature_select.c | 69 ++- source/blender/editors/armature/pose_select.c | 37 +- source/blender/editors/curve/editcurve_paint.c | 8 +- source/blender/editors/curve/editcurve_select.c | 103 +++-- source/blender/editors/include/ED_armature.h | 12 +- source/blender/editors/include/ED_curve.h | 14 +- source/blender/editors/include/ED_lattice.h | 6 +- source/blender/editors/include/ED_mball.h | 4 + source/blender/editors/include/ED_mesh.h | 9 +- source/blender/editors/include/ED_particle.h | 7 +- source/blender/editors/include/ED_sculpt.h | 2 +- .../blender/editors/lattice/editlattice_select.c | 66 ++- source/blender/editors/mesh/editface.c | 91 ++-- source/blender/editors/mesh/editmesh_select.c | 30 ++ source/blender/editors/metaball/mball_edit.c | 45 +- source/blender/editors/physics/particle_edit.c | 180 +++++--- source/blender/editors/sculpt_paint/paint_mask.c | 4 +- source/blender/editors/sculpt_paint/paint_utils.c | 8 +- .../blender/editors/space_view3d/view3d_select.c | 469 +++++++++++++-------- source/blender/makesdna/DNA_curve_types.h | 4 + 22 files changed, 809 insertions(+), 443 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h index fc065279aa3..0c2a3c28da9 100644 --- a/source/blender/blenkernel/BKE_mball.h +++ b/source/blender/blenkernel/BKE_mball.h @@ -22,6 +22,7 @@ /** \file * \ingroup bke */ +struct Base; struct BoundBox; struct Depsgraph; struct Main; @@ -39,7 +40,7 @@ struct MetaBall *BKE_mball_copy(struct Main *bmain, const struct MetaBall *mb); void BKE_mball_make_local(struct Main *bmain, struct MetaBall *mb, const bool lib_local); bool BKE_mball_is_any_selected(const struct MetaBall *mb); -bool BKE_mball_is_any_selected_multi(struct Object **objects, int objects_len); +bool BKE_mball_is_any_selected_multi(struct Base **bases, int bases_len); bool BKE_mball_is_any_unselected(const struct MetaBall *mb); bool BKE_mball_is_basis_for(struct Object *ob1, struct Object *ob2); bool BKE_mball_is_basis(struct Object *ob); @@ -63,13 +64,13 @@ void BKE_mball_translate(struct MetaBall *mb, const float offset[3]); struct MetaElem *BKE_mball_element_add(struct MetaBall *mb, const int type); int BKE_mball_select_count(const struct MetaBall *mb); -int BKE_mball_select_count_multi(struct Object **objects, int objects_len); -void BKE_mball_select_all(struct MetaBall *mb); -void BKE_mball_select_all_multi(struct Object **objects, int objects_len); -void BKE_mball_deselect_all(struct MetaBall *mb); -void BKE_mball_deselect_all_multi(struct Object **objects, int objects_len); -void BKE_mball_select_swap(struct MetaBall *mb); -void BKE_mball_select_swap_multi(struct Object **objects, int objects_len); +int BKE_mball_select_count_multi(struct Base **bases, int bases_len); +bool BKE_mball_select_all(struct MetaBall *mb); +bool BKE_mball_select_all_multi_ex(struct Base **bases, int bases_len); +bool BKE_mball_deselect_all(struct MetaBall *mb); +bool BKE_mball_deselect_all_multi_ex(struct Base **bases, int bases_len); +bool BKE_mball_select_swap(struct MetaBall *mb); +bool BKE_mball_select_swap_multi_ex(struct Base **bases, int bases_len); /* **** Depsgraph evaluation **** */ diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index d8aabcb6258..6a28c341fac 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -331,10 +331,10 @@ bool BKE_mball_is_any_selected(const MetaBall *mb) } -bool BKE_mball_is_any_selected_multi(Object **objects, int objects_len) +bool BKE_mball_is_any_selected_multi(Base **bases, int bases_len) { - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *obedit = bases[base_index]->object; MetaBall *mb = (MetaBall *)obedit->data; if (BKE_mball_is_any_selected(mb)) { return true; @@ -559,64 +559,83 @@ int BKE_mball_select_count(const MetaBall *mb) return sel; } -int BKE_mball_select_count_multi(Object **objects, int objects_len) +int BKE_mball_select_count_multi(Base **bases, int bases_len) { int sel = 0; - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - const Object *obedit = objects[ob_index]; + for (uint ob_index = 0; ob_index < bases_len; ob_index++) { + const Object *obedit = bases[ob_index]->object; const MetaBall *mb = (MetaBall *)obedit->data; sel += BKE_mball_select_count(mb); } return sel; } -void BKE_mball_select_all(MetaBall *mb) +bool BKE_mball_select_all(MetaBall *mb) { + bool changed = false; for (MetaElem *ml = mb->editelems->first; ml; ml = ml->next) { - ml->flag |= SELECT; + if ((ml->flag & SELECT) == 0) { + ml->flag |= SELECT; + changed = true; + } } + return changed; } -void BKE_mball_select_all_multi(Object **objects, int objects_len) +bool BKE_mball_select_all_multi_ex(Base **bases, int bases_len) { - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; + bool changed_multi = false; + for (uint ob_index = 0; ob_index < bases_len; ob_index++) { + Object *obedit = bases[ob_index]->object; MetaBall *mb = obedit->data; - BKE_mball_select_all(mb); + changed_multi |= BKE_mball_select_all(mb); } + return changed_multi; } -void BKE_mball_deselect_all(MetaBall *mb) +bool BKE_mball_deselect_all(MetaBall *mb) { + bool changed = false; for (MetaElem *ml = mb->editelems->first; ml; ml = ml->next) { - ml->flag &= ~SELECT; + if ((ml->flag & SELECT) != 0) { + ml->flag &= ~SELECT; + changed = true; + } } + return changed; } -void BKE_mball_deselect_all_multi(Object **objects, int objects_len) +bool BKE_mball_deselect_all_multi_ex(Base **bases, int bases_len) { - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; + bool changed_multi = false; + for (uint ob_index = 0; ob_index < bases_len; ob_index++) { + Object *obedit = bases[ob_index]->object; MetaBall *mb = obedit->data; - - BKE_mball_deselect_all(mb); + changed_multi |= BKE_mball_deselect_all(mb); + DEG_id_tag_update(&mb->id, ID_RECALC_SELECT); } + return changed_multi; } -void BKE_mball_select_swap(MetaBall *mb) +bool BKE_mball_select_swap(MetaBall *mb) { + bool changed = false; for (MetaElem *ml = mb->editelems->first; ml; ml = ml->next) { ml->flag ^= SELECT; + changed = true; } + return changed; } -void BKE_mball_select_swap_multi(Object **objects, int objects_len) +bool BKE_mball_select_swap_multi_ex(Base **bases, int bases_len) { - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; + bool changed_multi = false; + for (uint ob_index = 0; ob_index < bases_len; ob_index++) { + Object *obedit = bases[ob_index]->object; MetaBall *mb = (MetaBall *)obedit->data; - BKE_mball_select_swap(mb); + changed_multi |= BKE_mball_select_swap(mb); } + return changed_multi; } /* **** Depsgraph evaluation **** */ diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index b10db511eb4..6e93ecc484d 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -561,46 +561,69 @@ cache_end: return NULL; } -void ED_armature_edit_deselect_all(Object *obedit) +bool ED_armature_edit_deselect_all(Object *obedit) { bArmature *arm = obedit->data; - EditBone *ebone; - - for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { - ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + bool changed = false; + for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) { + if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) { + ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + changed = true; + } } + return changed; } -void ED_armature_edit_deselect_all_visible(Object *obedit) +bool ED_armature_edit_deselect_all_visible(Object *obedit) { bArmature *arm = obedit->data; - EditBone *ebone; - - for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { + bool changed = false; + for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) { /* first and foremost, bone must be visible and selected */ if (EBONE_VISIBLE(arm, ebone)) { - ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) { + ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + changed = true; + } } } - ED_armature_edit_sync_selection(arm->edbo); + if (changed) { + ED_armature_edit_sync_selection(arm->edbo); + } + return changed; } -void ED_armature_edit_deselect_all_multi(struct Object **objects, uint objects_len) +bool ED_armature_edit_deselect_all_multi_ex(struct Base **bases, uint bases_len) { - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - ED_armature_edit_deselect_all(obedit); + bool changed_multi = false; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *obedit = bases[base_index]->object; + changed_multi |= ED_armature_edit_deselect_all(obedit); } + return changed_multi; } -void ED_armature_edit_deselect_all_visible_multi(struct Object **objects, uint objects_len) +bool ED_armature_edit_deselect_all_visible_multi_ex(struct Base **bases, uint bases_len) { - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - ED_armature_edit_deselect_all_visible(obedit); + bool changed_multi = false; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *obedit = bases[base_index]->object; + changed_multi |= ED_armature_edit_deselect_all_visible(obedit); } + return changed_multi; +} + +bool ED_armature_edit_deselect_all_visible_multi(bContext *C) +{ + ViewContext vc; + ED_view3d_viewcontext_init(C, &vc); + uint bases_len = 0; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &bases_len); + bool changed_multi = ED_armature_edit_deselect_all_multi_ex(bases, bases_len); + MEM_freeN(bases); + return changed_multi; } /* accounts for connected parents */ @@ -636,10 +659,10 @@ bool ED_armature_edit_select_pick(bContext *C, const int mval[2], bool extend, b } if (!extend && !deselect && !toggle) { - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &objects_len); - ED_armature_edit_deselect_all_multi(objects, objects_len); - MEM_freeN(objects); + 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); } /* by definition the non-root connected bones have no root point drawn, diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index 285901f8dd0..5ef61f0f6c6 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -172,10 +172,10 @@ bool ED_armature_pose_select_pick_with_buffer( if (!extend && !deselect && !toggle) { { - uint objects_len = 0; - Object **objects = BKE_object_pose_array_get_unique(view_layer, v3d, &objects_len); - ED_pose_deselect_all_multi(objects, objects_len, SEL_DESELECT, true); - MEM_freeN(objects); + uint bases_len = 0; + Base **bases = BKE_object_pose_base_array_get_unique(view_layer, v3d, &bases_len); + ED_pose_deselect_all_multi_ex(bases, bases_len, SEL_DESELECT, true); + MEM_freeN(bases); } nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); arm->act_bone = nearBone; @@ -283,10 +283,10 @@ static bool ed_pose_is_any_selected(Object *ob, bool ignore_visibility) return false; } -static bool ed_pose_is_any_selected_multi(Object **objects, uint objects_len, bool ignore_visibility) +static bool ed_pose_is_any_selected_multi(Base **bases, uint bases_len, bool ignore_visibility) { - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *ob_iter = objects[ob_index]; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *ob_iter = bases[base_index]->object; if (ed_pose_is_any_selected(ob_iter, ignore_visibility)) { return true; } @@ -294,19 +294,34 @@ static bool ed_pose_is_any_selected_multi(Object **objects, uint objects_len, bo return false; } -void ED_pose_deselect_all_multi(Object **objects, uint objects_len, int select_mode, const bool ignore_visibility) +bool ED_pose_deselect_all_multi_ex(Base **bases, uint bases_len, int select_mode, const bool ignore_visibility) { if (select_mode == SEL_TOGGLE) { select_mode = ed_pose_is_any_selected_multi( - objects, objects_len, ignore_visibility) ? SEL_DESELECT : SEL_SELECT; + bases, bases_len, ignore_visibility) ? SEL_DESELECT : SEL_SELECT; } - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *ob_iter = objects[ob_index]; + bool changed_multi = false; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *ob_iter = bases[base_index]->object; if (ED_pose_deselect_all(ob_iter, select_mode, ignore_visibility)) { ED_pose_bone_select_tag_update(ob_iter); + changed_multi = true; } } + return changed_multi; +} + + +bool ED_pose_deselect_all_multi(bContext *C, int select_mode, const bool ignore_visibility) +{ + ViewContext vc; + ED_view3d_viewcontext_init(C, &vc); + uint bases_len = 0; + Base **bases = BKE_view_layer_array_from_bases_in_mode(vc.view_layer, vc.v3d, &bases_len, {.object_mode = OB_MODE_POSE,}); + bool changed_multi = ED_pose_deselect_all_multi_ex(bases, bases_len, select_mode, ignore_visibility); + MEM_freeN(bases); + return changed_multi; } /* ***************** Selections ********************** */ diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c index 0edee8a84ea..d930174c25b 100644 --- a/source/blender/editors/curve/editcurve_paint.c +++ b/source/blender/editors/curve/editcurve_paint.c @@ -784,13 +784,7 @@ static int curve_draw_exec(bContext *C, wmOperator *op) } /* Deselect all existing curves. */ - { - ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - ED_curve_deselect_all_multi(objects, objects_len); - MEM_freeN(objects); - } + ED_curve_deselect_all_multi(C); const float radius_min = cps->radius_min; const float radius_max = cps->radius_max; diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c index c52e5d3d787..7ba1b6b0cef 100644 --- a/source/blender/editors/curve/editcurve_select.c +++ b/source/blender/editors/curve/editcurve_select.c @@ -163,15 +163,18 @@ int ED_curve_nurb_select_count(View3D *v3d, Nurb *nu) return sel; } -void ED_curve_nurb_select_all(Nurb *nu) +bool ED_curve_nurb_select_all(const Nurb *nu) { + bool changed = false; int i; - if (nu->bezt) { BezTriple *bezt; for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { if (bezt->hide == 0) { - BEZT_SEL_ALL(bezt); + if (BEZT_ISSEL_ALL(bezt) == false) { + BEZT_SEL_ALL(bezt); + changed = true; + } } } } @@ -179,36 +182,48 @@ void ED_curve_nurb_select_all(Nurb *nu) BPoint *bp; for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) { if (bp->hide == 0) { - bp->f1 |= SELECT; + if ((bp->f1 & SELECT) == 0) { + bp->f1 |= SELECT; + changed = true; + } } } } + return changed; } -void ED_curve_select_all(EditNurb *editnurb) +bool ED_curve_select_all(EditNurb *editnurb) { - Nurb *nu; - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { - ED_curve_nurb_select_all(nu); + bool changed = false; + for (Nurb *nu = editnurb->nurbs.first; nu; nu = nu->next) { + changed |= ED_curve_nurb_select_all(nu); } + return changed; } -void ED_curve_nurb_deselect_all(Nurb *nu) +bool ED_curve_nurb_deselect_all(const Nurb *nu) { + bool changed = false; int i; - if (nu->bezt) { BezTriple *bezt; for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { - BEZT_DESEL_ALL(bezt); + if (BEZT_ISSEL_ANY(bezt)) { + BEZT_DESEL_ALL(bezt); + changed = true; + } } } else if (nu->bp) { BPoint *bp; for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) { - bp->f1 &= ~SELECT; + if (bp->f1 & SELECT) { + bp->f1 &= ~SELECT; + changed = true; + } } } + return changed; } int ED_curve_select_count(View3D *v3d, struct EditNurb *editnurb) @@ -236,30 +251,45 @@ bool ED_curve_select_check(View3D *v3d, struct EditNurb *editnurb) return false; } -void ED_curve_deselect_all(EditNurb *editnurb) +bool ED_curve_deselect_all(EditNurb *editnurb) { - Nurb *nu; - - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { - ED_curve_nurb_deselect_all(nu); + bool changed = false; + for (Nurb *nu = editnurb->nurbs.first; nu; nu = nu->next) { + changed |= ED_curve_nurb_deselect_all(nu); } + return changed; } -void ED_curve_deselect_all_multi(Object **objects, int objects_len) +bool ED_curve_deselect_all_multi_ex(Base **bases, int bases_len) { - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; + bool changed_multi = false; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *obedit = bases[base_index]->object; Curve *cu = obedit->data; - ED_curve_deselect_all(cu->editnurb); + changed_multi |= ED_curve_deselect_all(cu->editnurb); + DEG_id_tag_update(&cu->id, ID_RECALC_SELECT); } + return changed_multi; +} + +bool ED_curve_deselect_all_multi(struct bContext *C) +{ + ViewContext vc; + ED_view3d_viewcontext_init(C, &vc); + uint bases_len = 0; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &bases_len); + bool changed_multi = ED_curve_deselect_all_multi_ex(bases, bases_len); + MEM_freeN(bases); + return changed_multi; } -void ED_curve_select_swap(EditNurb *editnurb, bool hide_handles) +bool ED_curve_select_swap(EditNurb *editnurb, bool hide_handles) { Nurb *nu; BPoint *bp; BezTriple *bezt; int a; + bool changed = false; for (nu = editnurb->nurbs.first; nu; nu = nu->next) { if (nu->type == CU_BEZIER) { @@ -272,6 +302,7 @@ void ED_curve_select_swap(EditNurb *editnurb, bool hide_handles) bezt->f1 ^= SELECT; bezt->f3 ^= SELECT; } + changed = true; } bezt++; } @@ -280,11 +311,15 @@ void ED_curve_select_swap(EditNurb *editnurb, bool hide_handles) bp = nu->bp; a = nu->pntsu * nu->pntsv; while (a--) { - swap_selection_bpoint(bp); + if (bp->hide == 0) { + swap_selection_bpoint(bp); + changed = true; + } bp++; } } } + return changed; } /** @@ -489,7 +524,6 @@ static int de_select_all_exec(bContext *C, wmOperator *op) View3D *v3d = CTX_wm_view3d(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - if (action == SEL_TOGGLE) { action = SEL_SELECT; for (uint ob_index = 0; ob_index < objects_len; ob_index++) { @@ -506,22 +540,25 @@ static int de_select_all_exec(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Curve *cu = obedit->data; + bool changed = false; switch (action) { case SEL_SELECT: - ED_curve_select_all(cu->editnurb); + changed = ED_curve_select_all(cu->editnurb); break; case SEL_DESELECT: - ED_curve_deselect_all(cu->editnurb); + changed = ED_curve_deselect_all(cu->editnurb); break; case SEL_INVERT: - ED_curve_select_swap(cu->editnurb, (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0); + changed = ED_curve_select_swap(cu->editnurb, (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0); break; } - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - BKE_curve_nurb_vert_active_validate(cu); + if (changed) { + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + BKE_curve_nurb_vert_active_validate(cu); + } } MEM_freeN(objects); @@ -567,8 +604,7 @@ static int select_linked_exec(bContext *C, wmOperator *UNUSED(op)) for (nu = nurbs->first; nu; nu = nu->next) { if (ED_curve_nurb_select_check(v3d, nu)) { - ED_curve_nurb_select_all(nu); - changed = true; + changed |= ED_curve_nurb_select_all(nu); } } @@ -1634,8 +1670,7 @@ static int curve_select_similar_exec(bContext *C, wmOperator *op) case SIMCURHAND_TYPE: { if (nu->type & type_ref) { - ED_curve_nurb_select_all(nu); - changed = true; + changed |= ED_curve_nurb_select_all(nu); } break; } diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index 3d4ca7bf3be..d469c0ea8a0 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -154,11 +154,12 @@ void ED_armature_from_edit(struct Main *bmain, struct bArmature *arm); void ED_armature_to_edit(struct bArmature *arm); void ED_armature_edit_free(struct bArmature *arm); -void ED_armature_edit_deselect_all(struct Object *obedit); -void ED_armature_edit_deselect_all_visible(struct Object *obedit); +bool ED_armature_edit_deselect_all(struct Object *obedit); +bool ED_armature_edit_deselect_all_visible(struct Object *obedit); -void ED_armature_edit_deselect_all_multi(struct Object **objects, uint objects_len); -void ED_armature_edit_deselect_all_visible_multi(struct Object **objects, uint objects_len); +bool ED_armature_edit_deselect_all_multi_ex(struct Base **bases, uint bases_len); +bool ED_armature_edit_deselect_all_visible_multi_ex(struct Base **bases, uint bases_len); +bool ED_armature_edit_deselect_all_visible_multi(struct bContext *C); bool ED_armature_pose_select_pick_with_buffer( struct ViewLayer *view_layer, struct View3D *v3d, struct Base *base, const unsigned int *buffer, short hits, @@ -239,8 +240,9 @@ bool ED_object_posemode_exit_ex(struct Main *bmain, struct Object *ob); bool ED_object_posemode_exit(struct bContext *C, struct Object *ob); bool ED_object_posemode_enter_ex(struct Main *bmain, struct Object *ob); bool ED_object_posemode_enter(struct bContext *C, struct Object *ob); +bool ED_pose_deselect_all_multi_ex(struct Base **bases, uint bases_len, int select_mode, const bool ignore_visibility); +bool ED_pose_deselect_all_multi(struct bContext *C, int select_mode, const bool ignore_visibility); bool ED_pose_deselect_all(struct Object *ob, int select_mode, const bool ignore_visibility); -void ED_pose_deselect_all_multi(struct Object **objects, uint objects_len, int select_mode, const bool ignore_visibility); void ED_pose_bone_select_tag_update(struct Object *ob); void ED_pose_bone_select(struct Object *ob, struct bPoseChannel *pchan, bool select); void ED_pose_recalculate_paths(struct bContext *C, struct Scene *scene, struct Object *ob, bool current_frame_only); diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h index b585dc766d7..3e8821efbd0 100644 --- a/source/blender/editors/include/ED_curve.h +++ b/source/blender/editors/include/ED_curve.h @@ -25,6 +25,7 @@ #define __ED_CURVE_H__ struct BPoint; +struct Base; struct BezTriple; struct Curve; struct EditNurb; @@ -56,17 +57,18 @@ struct Nurb *ED_curve_add_nurbs_primitive(struct bContext *C, struct Object *obe bool ED_curve_nurb_select_check(struct View3D *v3d, struct Nurb *nu); int ED_curve_nurb_select_count(struct View3D *v3d, struct Nurb *nu); -void ED_curve_nurb_select_all(struct Nurb *nu); -void ED_curve_nurb_deselect_all(struct Nurb *nu); +bool ED_curve_nurb_select_all(const struct Nurb *nu); +bool ED_curve_nurb_deselect_all(const struct Nurb *nu); int join_curve_exec(struct bContext *C, struct wmOperator *op); /* editcurve_select.c */ bool ED_curve_select_check(struct View3D *v3d, struct EditNurb *editnurb); -void ED_curve_deselect_all(struct EditNurb *editnurb); -void ED_curve_deselect_all_multi(struct Object **objects, int objects_len); -void ED_curve_select_all(struct EditNurb *editnurb); -void ED_curve_select_swap(struct EditNurb *editnurb, bool hide_handles); +bool ED_curve_deselect_all(struct EditNurb *editnurb); +bool ED_curve_deselect_all_multi_ex(struct Base **bases, int bases_len); +bool ED_curve_deselect_all_multi(struct bContext *C); +bool ED_curve_select_all(struct EditNurb *editnurb); +bool ED_curve_select_swap(struct EditNurb *editnurb, bool hide_handles); int ED_curve_select_count(struct View3D *v3d, struct EditNurb *editnurb); /* editcurve_undo.c */ diff --git a/source/blender/editors/include/ED_lattice.h b/source/blender/editors/include/ED_lattice.h index 98a091861d1..f65f47c40ad 100644 --- a/source/blender/editors/include/ED_lattice.h +++ b/source/blender/editors/include/ED_lattice.h @@ -24,6 +24,7 @@ #ifndef __ED_LATTICE_H__ #define __ED_LATTICE_H__ +struct Base; struct Object; struct UndoType; struct wmKeyConfig; @@ -33,9 +34,12 @@ void ED_operatortypes_lattice(void); void ED_keymap_lattice(struct wmKeyConfig *keyconf); /* editlattice_select.c */ -void ED_lattice_flags_set(struct Object *obedit, int flag); +bool ED_lattice_flags_set(struct Object *obedit, int flag); bool ED_lattice_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle); +bool ED_lattice_deselect_all_multi_ex(struct Base **bases, const uint bases_len); +bool ED_lattice_deselect_all_multi(struct bContext *C); + /* editlattice_undo.c */ void ED_lattice_undosys_type(struct UndoType *ut); diff --git a/source/blender/editors/include/ED_mball.h b/source/blender/editors/include/ED_mball.h index e1033866193..2683631e85f 100644 --- a/source/blender/editors/include/ED_mball.h +++ b/source/blender/editors/include/ED_mball.h @@ -24,6 +24,7 @@ #ifndef __ED_MBALL_H__ #define __ED_MBALL_H__ +struct Base; struct Object; struct UndoType; struct bContext; @@ -37,6 +38,9 @@ struct MetaElem *ED_mball_add_primitive(struct bContext *C, struct Object *obedi bool ED_mball_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle); +bool ED_mball_deselect_all_multi_ex(struct Base **bases, uint bases_len); +bool ED_mball_deselect_all_multi(struct bContext *C); + void ED_mball_editmball_free(struct Object *obedit); void ED_mball_editmball_make(struct Object *obedit); void ED_mball_editmball_load(struct Object *obedit); diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index b912cf88102..9e68c4a03ae 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -203,6 +203,9 @@ void EDBM_select_swap(struct BMEditMesh *em); /* exported for UV */ bool EDBM_select_interior_faces(struct BMEditMesh *em); void em_setup_viewcontext(struct bContext *C, struct ViewContext *vc); /* rename? */ +bool EDBM_mesh_deselect_all_multi_ex(struct Base **bases, const uint bases_len); +bool EDBM_mesh_deselect_all_multi(struct bContext *C); + extern unsigned int bm_vertoffs, bm_solidoffs, bm_wireoffs; /* editmesh_preselect_edgering.c */ @@ -237,15 +240,15 @@ void EDBM_project_snap_verts(struct bContext *C, struct ARegion *ar, struct BMEd /* editface.c */ void paintface_flush_flags(struct bContext *C, struct Object *ob, short flag); bool paintface_mouse_select(struct bContext *C, struct Object *ob, const int mval[2], bool extend, bool deselect, bool toggle); -int do_paintface_box_select(struct ViewContext *vc, const struct rcti *rect, int sel_op); -void paintface_deselect_all_visible(struct bContext *C, struct Object *ob, int action, bool flush_flags); +bool do_paintface_box_select(struct ViewContext *vc, const struct rcti *rect, int sel_op); +bool paintface_deselect_all_visible(struct bContext *C, struct Object *ob, int action, bool flush_flags); void paintface_select_linked(struct bContext *C, struct Object *ob, const int mval[2], const bool select); bool paintface_minmax(struct Object *ob, float r_min[3], float r_max[3]); void paintface_hide(struct bContext *C, struct Object *ob, const bool unselected); void paintface_reveal(struct bContext *C, struct Object *ob, const bool select); -void paintvert_deselect_all_visible(struct Object *ob, int action, bool flush_flags); +bool paintvert_deselect_all_visible(struct Object *ob, int action, bool flush_flags); void paintvert_select_ungrouped(struct Object *ob, bool extend, bool flush_flags); void paintvert_flush_flags(struct Object *ob); void paintvert_tag_select_update(struct bContext *C, struct Object *ob); diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h index bbecffee9c0..6731d878dc6 100644 --- a/source/blender/editors/include/ED_particle.h +++ b/source/blender/editors/include/ED_particle.h @@ -53,11 +53,12 @@ void PE_update_object( struct Object *ob, int useflag); /* selection tools */ -int PE_mouse_particles(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle); -int PE_box_select(struct bContext *C, const struct rcti *rect, const int sel_op); +bool PE_mouse_particles(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle); +bool PE_box_select(struct bContext *C, const struct rcti *rect, const int sel_op); bool PE_circle_select(struct bContext *C, int sel_op, const int mval[2], float rad); int PE_lasso_select(struct bContext *C, const int mcords[][2], const short moves, const int sel_op); -void PE_deselect_all_visible(struct PTCacheEdit *edit); +bool PE_deselect_all_visible_ex(struct PTCacheEdit *edit); +bool PE_deselect_all_visible(struct bContext *C); /* particle_edit_undo.c */ void ED_particle_undosys_type(struct UndoType *ut); diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h index ce234b5fb12..31b642165cd 100644 --- a/source/blender/editors/include/ED_sculpt.h +++ b/source/blender/editors/include/ED_sculpt.h @@ -37,7 +37,7 @@ struct rcti; /* sculpt.c */ void ED_operatortypes_sculpt(void); void ED_sculpt_redraw_planes_get(float planes[4][4], struct ARegion *ar, struct Object *ob); -int ED_sculpt_mask_box_select(struct bContext *C, struct ViewContext *vc, const struct rcti *rect, bool select); +bool ED_sculpt_mask_box_select(struct bContext *C, struct ViewContext *vc, const struct rcti *rect, bool select); /* sculpt_undo.c */ void ED_sculpt_undosys_type(struct UndoType *ut); diff --git a/source/blender/editors/lattice/editlattice_select.c b/source/blender/editors/lattice/editlattice_select.c index 2c7f084fe17..a92ed02c483 100644 --- a/source/blender/editors/lattice/editlattice_select.c +++ b/source/blender/editors/lattice/editlattice_select.c @@ -75,6 +75,29 @@ static void bpoint_select_set(BPoint *bp, bool select) } } +bool ED_lattice_deselect_all_multi_ex(struct Base **bases, const uint bases_len) +{ + bool changed_multi = false; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Base *base_iter = bases[base_index]; + Object *ob_iter = base_iter->object; + changed_multi |= ED_lattice_flags_set(ob_iter, 0); + DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT); + } + return changed_multi; +} + +bool ED_lattice_deselect_all_multi(struct bContext *C) +{ + ViewContext vc; + ED_view3d_viewcontext_init(C, &vc); + uint bases_len = 0; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &bases_len); + bool changed_multi = ED_lattice_deselect_all_multi_ex(bases, bases_len); + MEM_freeN(bases); + return changed_multi; +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -356,23 +379,32 @@ void LATTICE_OT_select_less(wmOperatorType *ot) /** \name Select All Operator * \{ */ -void ED_lattice_flags_set(Object *obedit, int flag) +bool ED_lattice_flags_set(Object *obedit, int flag) { Lattice *lt = obedit->data; BPoint *bp; int a; + bool changed = false; bp = lt->editlatt->latt->def; a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; - lt->editlatt->latt->actbp = LT_ACTBP_NONE; + + if (lt->editlatt->latt->actbp != LT_ACTBP_NONE) { + lt->editlatt->latt->actbp = LT_ACTBP_NONE; + changed = true; + } while (a--) { if (bp->hide == 0) { - bp->f1 = flag; + if (bp->f1 != flag) { + bp->f1 = flag; + changed = true; + } } bp++; } + return changed; } static int lattice_select_all_exec(bContext *C, wmOperator *op) @@ -395,18 +427,20 @@ static int lattice_select_all_exec(bContext *C, wmOperator *op) } } + bool changed_multi = false; for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; Lattice *lt; BPoint *bp; int a; + bool changed = false; switch (action) { case SEL_SELECT: - ED_lattice_flags_set(obedit, 1); + changed = ED_lattice_flags_set(obedit, 1); break; case SEL_DESELECT: - ED_lattice_flags_set(obedit, 0); + changed = ED_lattice_flags_set(obedit, 0); break; case SEL_INVERT: lt = obedit->data; @@ -417,18 +451,24 @@ static int lattice_select_all_exec(bContext *C, wmOperator *op) while (a--) { if (bp->hide == 0) { bp->f1 ^= SELECT; + changed = true; } bp++; } break; } - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + if (changed) { + changed_multi = true; + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + } } MEM_freeN(objects); - - return OPERATOR_FINISHED; + if (changed_multi) { + return OPERATOR_FINISHED; + } + return OPERATOR_CANCELLED; } void LATTICE_OT_select_all(wmOperatorType *ot) @@ -597,10 +637,10 @@ bool ED_lattice_select_pick(bContext *C, const int mval[2], bool extend, bool de Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; - ED_lattice_flags_set(ob, 0); - - DEG_id_tag_update(ob->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); + if (ED_lattice_flags_set(ob, 0)) { + DEG_id_tag_update(ob->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); + } } MEM_freeN(objects); } diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 12a96d41711..842394f1107 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -282,14 +282,16 @@ void paintface_select_linked(bContext *C, Object *ob, const int mval[2], const b paintface_flush_flags(C, ob, SELECT); } -void paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool flush_flags) +bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool flush_flags) { Mesh *me; MPoly *mpoly; int a; me = BKE_mesh_from_object(ob); - if (me == NULL) return; + if (me == NULL) { + return false; + } if (action == SEL_TOGGLE) { action = SEL_SELECT; @@ -305,28 +307,40 @@ void paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl } } + bool changed = false; + mpoly = me->mpoly; a = me->totpoly; while (a--) { if ((mpoly->flag & ME_HIDE) == 0) { switch (action) { case SEL_SELECT: - mpoly->flag |= ME_FACE_SEL; + if ((mpoly->flag & ME_FACE_SEL) == 0) { + mpoly->flag |= ME_FACE_SEL; + changed = true; + } break; case SEL_DESELECT: - mpoly->flag &= ~ME_FACE_SEL; + if ((mpoly->flag & ME_FACE_SEL) != 0) { + mpoly->flag &= ~ME_FACE_SEL; + changed = true; + } break; case SEL_INVERT: mpoly->flag ^= ME_FACE_SEL; + changed = true; break; } } mpoly++; } - if (flush_flags) { - paintface_flush_flags(C, ob, SELECT); + if (changed) { + if (flush_flags) { + paintface_flush_flags(C, ob, SELECT); + } } + return changed; } bool paintface_minmax(Object *ob, float r_min[3], float r_max[3]) @@ -389,10 +403,7 @@ bool paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], b mpoly = me->mpoly; a = me->totpoly; if (!extend && !deselect && !toggle) { - while (a--) { - mpoly->flag &= ~ME_FACE_SEL; - mpoly++; - } + paintface_deselect_all_visible(C, ob, SEL_DESELECT, false); } me->act_face = (int)index; @@ -420,7 +431,7 @@ bool paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], b return true; } -int do_paintface_box_select(ViewContext *vc, const rcti *rect, int sel_op) +bool do_paintface_box_select(ViewContext *vc, const rcti *rect, int sel_op) { Object *ob = vc->obact; Mesh *me; @@ -431,13 +442,14 @@ int do_paintface_box_select(ViewContext *vc, const rcti *rect, int sel_op) me = BKE_mesh_from_object(ob); if ((me == NULL) || (me->totpoly == 0) || BLI_rcti_is_empty(rect)) { - return OPERATOR_CANCELLED; + return false; } selar = MEM_callocN(me->totpoly + 1, "selar"); + bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - paintface_deselect_all_visible(vc->C, vc->obact, SEL_DESELECT, false); + changed |= paintface_deselect_all_visible(vc->C, vc->obact, SEL_DESELECT, false); } uint buf_len; @@ -464,6 +476,7 @@ int do_paintface_box_select(ViewContext *vc, const rcti *rect, int sel_op) const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(mpoly->flag, sel_op_result, ME_FACE_SEL); + changed = true; } } } @@ -475,9 +488,10 @@ int do_paintface_box_select(ViewContext *vc, const rcti *rect, int sel_op) glReadBuffer(GL_BACK); #endif - paintface_flush_flags(vc->C, vc->obact, SELECT); - - return OPERATOR_FINISHED; + if (changed) { + paintface_flush_flags(vc->C, vc->obact, SELECT); + } + return changed; } @@ -536,14 +550,16 @@ void paintvert_tag_select_update(struct bContext *C, struct Object *ob) /* note: if the caller passes false to flush_flags, * then they will need to run paintvert_flush_flags(ob) themselves */ -void paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags) +bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags) { Mesh *me; MVert *mvert; int a; me = BKE_mesh_from_object(ob); - if (me == NULL) return; + if (me == NULL) { + return false; + } if (action == SEL_TOGGLE) { action = SEL_SELECT; @@ -559,39 +575,50 @@ void paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags) } } + bool changed = false; mvert = me->mvert; a = me->totvert; while (a--) { if ((mvert->flag & ME_HIDE) == 0) { switch (action) { case SEL_SELECT: - mvert->flag |= SELECT; + if ((mvert->flag & SELECT) == 0) { + mvert->flag |= SELECT; + changed = true; + } break; case SEL_DESELECT: - mvert->flag &= ~SELECT; + if ((mvert->flag & SELECT) != 0) { + mvert->flag &= ~SELECT; + changed = true; + } break; case SEL_INVERT: mvert->flag ^= SELECT; + changed = true; break; } } mvert++; } - /* handle mselect */ - if (action == SEL_SELECT) { - /* pass */ - } - else if (ELEM(action, SEL_DESELECT, SEL_INVERT)) { - BKE_mesh_mselect_clear(me); - } - else { - BKE_mesh_mselect_validate(me); - } + if (changed) { + /* handle mselect */ + if (action == SEL_SELECT) { + /* pass */ + } + else if (ELEM(action, SEL_DESELECT, SEL_INVERT)) { + BKE_mesh_mselect_clear(me); + } + else { + BKE_mesh_mselect_validate(me); + } - if (flush_flags) { - paintvert_flush_flags(ob); + if (flush_flags) { + paintvert_flush_flags(ob); + } } + return changed; } void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags) diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 991e0f94383..1855eeab944 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -2597,6 +2597,36 @@ void EDBM_select_swap(BMEditMesh *em) /* exported for UV */ } } +bool EDBM_mesh_deselect_all_multi_ex(struct Base **bases, const uint bases_len) +{ + bool changed_multi = false; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Base *base_iter = bases[base_index]; + Object *ob_iter = base_iter->object; + BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter); + + if (em_iter->bm->totvertsel == 0) { + continue; + } + + EDBM_flag_disable_all(em_iter, BM_ELEM_SELECT); + DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT); + changed_multi = true; + } + return changed_multi; +} + +bool EDBM_mesh_deselect_all_multi(struct bContext *C) +{ + ViewContext vc; + ED_view3d_viewcontext_init(C, &vc); + uint bases_len = 0; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &bases_len); + bool changed_multi = EDBM_mesh_deselect_all_multi_ex(bases, bases_len); + MEM_freeN(bases); + return changed_multi; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c index 8da87a4fdd1..84174459e50 100644 --- a/source/blender/editors/metaball/mball_edit.c +++ b/source/blender/editors/metaball/mball_edit.c @@ -125,35 +125,35 @@ static int mball_select_all_exec(bContext *C, wmOperator *op) int action = RNA_enum_get(op->ptr, "action"); ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); + uint bases_len = 0; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &bases_len); if (action == SEL_TOGGLE) { - action = BKE_mball_is_any_selected_multi(objects, objects_len) ? + action = BKE_mball_is_any_selected_multi(bases, bases_len) ? SEL_DESELECT : SEL_SELECT; } switch (action) { case SEL_SELECT: - BKE_mball_select_all_multi(objects, objects_len); + BKE_mball_select_all_multi_ex(bases, bases_len); break; case SEL_DESELECT: - BKE_mball_deselect_all_multi(objects, objects_len); + BKE_mball_deselect_all_multi_ex(bases, bases_len); break; case SEL_INVERT: - BKE_mball_select_swap_multi(objects, objects_len); + BKE_mball_select_swap_multi_ex(bases, bases_len); break; } - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *obedit = bases[base_index]->object; MetaBall *mb = (MetaBall *)obedit->data; DEG_id_tag_update(&mb->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb); } - MEM_freeN(objects); + MEM_freeN(bases); return OPERATOR_FINISHED; } @@ -315,10 +315,10 @@ static int mball_select_similar_exec(bContext *C, wmOperator *op) int tot_mball_selected_all = 0; ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); + uint bases_len = 0; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &bases_len); - tot_mball_selected_all = BKE_mball_select_count_multi(objects, objects_len); + tot_mball_selected_all = BKE_mball_select_count_multi(bases, bases_len); short type_ref = 0; KDTree_1d *tree_1d = NULL; @@ -335,8 +335,8 @@ static int mball_select_similar_exec(bContext *C, wmOperator *op) } /* Get type of selected MetaBall */ - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *obedit = bases[base_index]->object; MetaBall *mb = (MetaBall *)obedit->data; switch (type) { @@ -371,8 +371,8 @@ static int mball_select_similar_exec(bContext *C, wmOperator *op) BLI_kdtree_3d_balance(tree_3d); } /* Select MetaBalls with desired type. */ - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *obedit = bases[base_index]->object; MetaBall *mb = (MetaBall *)obedit->data; bool changed = false; @@ -405,7 +405,7 @@ static int mball_select_similar_exec(bContext *C, wmOperator *op) } } - MEM_freeN(objects); + MEM_freeN(bases); if (tree_1d != NULL) { BLI_kdtree_1d_free(tree_1d); } @@ -821,3 +821,14 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese return false; } + +bool ED_mball_deselect_all_multi(bContext *C) +{ + ViewContext vc; + ED_view3d_viewcontext_init(C, &vc); + uint bases_len = 0; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &bases_len); + bool changed_multi = BKE_mball_deselect_all_multi_ex(bases, bases_len); + MEM_freeN(bases); + return changed_multi; +} diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 392c82abbfc..bd7f06c9674 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -496,7 +496,7 @@ static void PE_free_random_generator(PEData *data) /*************************** selection utilities *******************************/ -static bool key_test_depth(PEData *data, const float co[3], const int screen_co[2]) +static bool key_test_depth(const PEData *data, const float co[3], const int screen_co[2]) { View3D *v3d = data->vc.v3d; ViewDepths *vd = data->vc.rv3d->depths; @@ -533,7 +533,7 @@ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[ return 1; } -static bool key_inside_circle(PEData *data, float rad, const float co[3], float *distance) +static bool key_inside_circle(const PEData *data, float rad, const float co[3], float *distance) { float dx, dy, dist; int screen_co[2]; @@ -1562,6 +1562,7 @@ static void select_key_op(PEData *data, int point_index, int key_index, bool is_ if (sel_op_result != -1) { SET_FLAG_FROM_TEST(key->flag, sel_op_result, PEK_SELECT); point->flag |= PEP_EDIT_RECALC; + data->is_changed = true; } } @@ -1587,8 +1588,11 @@ static void extend_key_select(PEData *data, int point_index, int key_index, bool PTCacheEditPoint *point = edit->points + point_index; PTCacheEditKey *key = point->keys + key_index; - key->flag |= PEK_SELECT; - point->flag |= PEP_EDIT_RECALC; + if ((key->flag & PEK_SELECT) == 0) { + key->flag |= PEK_SELECT; + point->flag |= PEP_EDIT_RECALC; + data->is_changed = true; + } } static void deselect_key_select(PEData *data, int point_index, int key_index, bool UNUSED(is_inside)) @@ -1597,8 +1601,11 @@ static void deselect_key_select(PEData *data, int point_index, int key_index, bo PTCacheEditPoint *point = edit->points + point_index; PTCacheEditKey *key = point->keys + key_index; - key->flag &= ~PEK_SELECT; - point->flag |= PEP_EDIT_RECALC; + if ((key->flag & PEK_SELECT) != 0) { + key->flag &= ~PEK_SELECT; + point->flag |= PEP_EDIT_RECALC; + data->is_changed = true; + } } static void toggle_key_select(PEData *data, int point_index, int key_index, bool UNUSED(is_inside)) @@ -1609,36 +1616,43 @@ static void toggle_key_select(PEData *data, int point_index, int key_index, bool key->flag ^= PEK_SELECT; point->flag |= PEP_EDIT_RECALC; + data->is_changed = true; } /************************ de select all operator ************************/ -static void select_action_apply(PTCacheEditPoint *point, PTCacheEditKey *key, int action) +static bool select_action_apply(PTCacheEditPoint *point, PTCacheEditKey *key, int action) { + bool changed = false; switch (action) { case SEL_SELECT: if ((key->flag & PEK_SELECT) == 0) { key->flag |= PEK_SELECT; point->flag |= PEP_EDIT_RECALC; + changed = true; } break; case SEL_DESELECT: if (key->flag & PEK_SELECT) { key->flag &= ~PEK_SELECT; point->flag |= PEP_EDIT_RECALC; + changed = true; } break; case SEL_INVERT: if ((key->flag & PEK_SELECT) == 0) { key->flag |= PEK_SELECT; point->flag |= PEP_EDIT_RECALC; + changed = true; } else { key->flag &= ~PEK_SELECT; point->flag |= PEP_EDIT_RECALC; + changed = true; } break; } + return changed; } static int pe_select_all_exec(bContext *C, wmOperator *op) @@ -1663,15 +1677,17 @@ static int pe_select_all_exec(bContext *C, wmOperator *op) } } + bool changed = false; LOOP_VISIBLE_POINTS { LOOP_VISIBLE_KEYS { - select_action_apply(point, key, action); + changed |= select_action_apply(point, key, action); } } - PE_update_selection(depsgraph, scene, ob, 1); - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob); - + if (changed) { + PE_update_selection(depsgraph, scene, ob, 1); + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob); + } return OPERATOR_FINISHED; } @@ -1694,7 +1710,7 @@ void PARTICLE_OT_select_all(wmOperatorType *ot) /************************ pick select operator ************************/ -int PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle) +bool PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle) { PEData data; Scene *scene = CTX_data_scene(C); @@ -1702,8 +1718,9 @@ int PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool deselec PTCacheEdit *edit = PE_get_current(scene, ob); POINT_P; KEY_K; - if (!PE_start_edit(edit)) - return OPERATOR_CANCELLED; + if (!PE_start_edit(edit)) { + return false; + } if (!extend && !deselect && !toggle) { LOOP_VISIBLE_POINTS { @@ -1729,10 +1746,12 @@ int PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool deselec for_mouse_hit_keys(&data, toggle_key_select, PSEL_NEAREST); } - PE_update_selection(data.depsgraph, scene, ob, 1); - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob); + if (data.is_changed) { + PE_update_selection(data.depsgraph, scene, ob, 1); + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob); + } - return OPERATOR_FINISHED; + return true; } /************************ select root operator ************************/ @@ -1745,10 +1764,12 @@ static void select_root(PEData *data, int point_index) if (point->flag & PEP_HIDE) return; - if (data->select_action != SEL_TOGGLE) - select_action_apply(point, key, data->select_action); - else if (key->flag & PEK_SELECT) + if (data->select_action != SEL_TOGGLE) { + data->is_changed = select_action_apply(point, key, data->select_action); + } + else if (key->flag & PEK_SELECT) { data->select_toggle_action = SEL_DESELECT; + } } static int select_roots_exec(bContext *C, wmOperator *op) @@ -1770,9 +1791,10 @@ static int select_roots_exec(bContext *C, wmOperator *op) data.select_action = action; foreach_point(&data, select_root); - PE_update_selection(data.depsgraph, data.scene, data.ob, 1); - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob); - + if (data.is_changed) { + PE_update_selection(data.depsgraph, data.scene, data.ob, 1); + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob); + } return OPERATOR_FINISHED; } @@ -1810,10 +1832,12 @@ static void select_tip(PEData *data, int point_index) if (point->flag & PEP_HIDE) return; - if (data->select_action != SEL_TOGGLE) - select_action_apply(point, key, data->select_action); - else if (key->flag & PEK_SELECT) + if (data->select_action != SEL_TOGGLE) { + data->is_changed = select_action_apply(point, key, data->select_action); + } + else if (key->flag & PEK_SELECT) { data->select_toggle_action = SEL_DESELECT; + } } static int select_tips_exec(bContext *C, wmOperator *op) @@ -1835,10 +1859,13 @@ static int select_tips_exec(bContext *C, wmOperator *op) data.select_action = action; foreach_point(&data, select_tip); - PE_update_selection(data.depsgraph, data.scene, data.ob, 1); - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob); + if (data.is_changed) { + PE_update_selection(data.depsgraph, data.scene, data.ob, 1); + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; + } + return OPERATOR_CANCELLED; } void PARTICLE_OT_select_tips(wmOperatorType *ot) @@ -1899,7 +1926,7 @@ static int select_random_exec(bContext *C, wmOperator *op) LOOP_VISIBLE_POINTS { int flag = ((BLI_rng_get_float(rng) < randfac) == select) ? SEL_SELECT : SEL_DESELECT; LOOP_KEYS { - select_action_apply(point, key, flag); + data.is_changed = select_action_apply(point, key, flag); } } break; @@ -1907,7 +1934,7 @@ static int select_random_exec(bContext *C, wmOperator *op) LOOP_VISIBLE_POINTS { LOOP_VISIBLE_KEYS { int flag = ((BLI_rng_get_float(rng) < randfac) == select) ? SEL_SELECT : SEL_DESELECT; - select_action_apply(point, key, flag); + data.is_changed = select_action_apply(point, key, flag); } } break; @@ -1915,9 +1942,10 @@ static int select_random_exec(bContext *C, wmOperator *op) BLI_rng_free(rng); - PE_update_selection(data.depsgraph, data.scene, data.ob, 1); - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob); - + if (data.is_changed) { + PE_update_selection(data.depsgraph, data.scene, data.ob, 1); + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob); + } return OPERATOR_FINISHED; } @@ -1992,42 +2020,58 @@ void PARTICLE_OT_select_linked(wmOperatorType *ot) } /************************ box select operator ************************/ -void PE_deselect_all_visible(PTCacheEdit *edit) +bool PE_deselect_all_visible_ex(PTCacheEdit *edit) { + bool changed = false; POINT_P; KEY_K; LOOP_VISIBLE_POINTS { LOOP_SELECTED_KEYS { - key->flag &= ~PEK_SELECT; - point->flag |= PEP_EDIT_RECALC; + if ((key->flag & PEK_SELECT) != 0) { + key->flag &= ~PEK_SELECT; + point->flag |= PEP_EDIT_RECALC; + changed = true; + } } } + return changed; } -int PE_box_select(bContext *C, const rcti *rect, const int sel_op) +bool PE_deselect_all_visible(bContext *C) { Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); PTCacheEdit *edit = PE_get_current(scene, ob); - PEData data; + if (!PE_start_edit(edit)) { + return false; + } + return PE_deselect_all_visible_ex(edit); +} - if (!PE_start_edit(edit)) - return OPERATOR_CANCELLED; +bool PE_box_select(bContext *C, const rcti *rect, const int sel_op) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_active_object(C); + PTCacheEdit *edit = PE_get_current(scene, ob); + PEData data; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - PE_deselect_all_visible(edit); + if (!PE_start_edit(edit)) { + return false; } PE_set_view3d_data(C, &data); data.rect = rect; data.sel_op = sel_op; + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + data.is_changed = PE_deselect_all_visible_ex(edit); + } for_mouse_hit_keys(&data, select_key_op, PSEL_ALL_KEYS); - - PE_update_selection(data.depsgraph, scene, ob, 1); - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob); - - return OPERATOR_FINISHED; + if (data.is_changed) { + PE_update_selection(data.depsgraph, scene, ob, 1); + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob); + } + return data.is_changed; } /************************ circle select operator ************************/ @@ -2044,11 +2088,6 @@ bool PE_circle_select(bContext *C, const int sel_op, const int mval[2], float ra return false; } - bool changed = false; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - PE_deselect_all_visible(edit); - changed = true; - } const bool select = (sel_op != SEL_OP_SUB); PE_set_view3d_data(C, &data); @@ -2056,14 +2095,15 @@ bool PE_circle_select(bContext *C, const int sel_op, const int mval[2], float ra data.rad = rad; data.select = select; + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + data.is_changed = PE_deselect_all_visible_ex(edit); + } for_mouse_hit_keys(&data, select_key, 0); - changed |= data.is_changed; - - if (changed) { + if (data.is_changed) { PE_update_selection(data.depsgraph, scene, ob, 1); WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob); } - return changed; + return data.is_changed; } /************************ lasso select operator ************************/ @@ -2088,13 +2128,13 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, const if (!PE_start_edit(edit)) return OPERATOR_CANCELLED; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - PE_deselect_all_visible(edit); - } - /* only for depths */ PE_set_view3d_data(C, &data); + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + data.is_changed |= PE_deselect_all_visible_ex(edit); + } + LOOP_VISIBLE_POINTS { if (edit->psys && !(psys->flag & PSYS_GLOBAL_HAIR)) psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat); @@ -2112,6 +2152,7 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, const if (sel_op_result != -1) { SET_FLAG_FROM_TEST(key->flag, sel_op_result, PEK_SELECT); point->flag |= PEP_EDIT_RECALC; + data.is_changed = true; } } } @@ -2129,15 +2170,18 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, const if (sel_op_result != -1) { SET_FLAG_FROM_TEST(key->flag, sel_op_result, PEK_SELECT); point->flag |= PEP_EDIT_RECALC; + data.is_changed = true; } } } } - PE_update_selection(data.depsgraph, scene, ob, 1); - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob); - - return OPERATOR_FINISHED; + if (data.is_changed) { + PE_update_selection(data.depsgraph, scene, ob, 1); + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob); + return OPERATOR_FINISHED; + } + return OPERATOR_CANCELLED; } /*************************** hide operator **************************/ @@ -2267,9 +2311,10 @@ static void select_less_keys(PEData *data, int point_index) } LOOP_KEYS { - if (key->flag & PEK_TAG) { + if ((key->flag & PEK_TAG) && (key->flag & PEK_SELECT)) { key->flag &= ~(PEK_TAG | PEK_SELECT); point->flag |= PEP_EDIT_RECALC; /* redraw selection only */ + data->is_changed = true; } } } @@ -2328,10 +2373,11 @@ static void select_more_keys(PEData *data, int point_index) } LOOP_KEYS { - if (key->flag & PEK_TAG) { + if ((key->flag & PEK_TAG) && (key->flag & PEK_SELECT) == 0) { key->flag &= ~PEK_TAG; key->flag |= PEK_SELECT; point->flag |= PEP_EDIT_RECALC; /* redraw selection only */ + data->is_changed = true; } } } diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index 2f9706db636..b88ae861229 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -249,7 +249,7 @@ static void mask_box_select_task_cb( } BKE_pbvh_vertex_iter_end; } -int ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *rect, bool select) +bool ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *rect, bool select) { Depsgraph *depsgraph = CTX_data_depsgraph(C); Sculpt *sd = vc->scene->toolsettings->sculpt; @@ -321,7 +321,7 @@ int ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *r WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); - return OPERATOR_FINISHED; + return true; } typedef struct LassoMaskData { diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 2f7cd3fceba..35401c470cc 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -650,9 +650,11 @@ void PAINT_OT_face_select_linked_pick(wmOperatorType *ot) static int face_select_all_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); - paintface_deselect_all_visible(C, ob, RNA_enum_get(op->ptr, "action"), true); - ED_region_tag_redraw(CTX_wm_region(C)); - return OPERATOR_FINISHED; + if (paintface_deselect_all_visible(C, ob, RNA_enum_get(op->ptr, "action"), true)) { + ED_region_tag_redraw(CTX_wm_region(C)); + return OPERATOR_FINISHED; + } + return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 78a33a01908..b1513b9825b 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -459,7 +459,7 @@ static void do_lasso_tag_pose(ViewContext *vc, Object *ob, const int mcords[][2] pose_foreachScreenBone(&vc_tmp, do_lasso_select_pose__do_tag, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } -static void do_lasso_select_objects( +static bool do_lasso_select_objects( ViewContext *vc, const int mcords[][2], const short moves, const eSelectOp sel_op) { @@ -468,7 +468,7 @@ static void do_lasso_select_objects( bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - changed = object_deselect_all_visible(vc->view_layer, vc->v3d); + changed |= object_deselect_all_visible(vc->view_layer, vc->v3d); } for (base = vc->view_layer->object_bases.first; base; base = base->next) { @@ -489,6 +489,7 @@ static void do_lasso_select_objects( DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT); WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, vc->scene); } + return changed; } @@ -569,7 +570,7 @@ static bool do_pose_tag_select_op_exec(Base **bases, const uint bases_len, const return changed_multi; } -static void do_lasso_select_pose( +static bool do_lasso_select_pose( ViewContext *vc, const int mcords[][2], const short moves, const eSelectOp sel_op) { @@ -588,9 +589,8 @@ static void do_lasso_select_pose( WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, vc->scene); } - if (bases != NULL) { - MEM_freeN(bases); - } + MEM_freeN(bases); + return changed_multi; } static void do_lasso_select_mesh__doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index)) @@ -650,7 +650,7 @@ static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, cons } } -static void do_lasso_select_mesh( +static bool do_lasso_select_mesh( ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) { @@ -667,7 +667,10 @@ static void do_lasso_select_mesh( view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT); + if (vc->em->bm->totvertsel) { + EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT); + data.is_changed = true; + } } /* for non zbuf projections, don't change the GL state */ @@ -678,7 +681,7 @@ static void do_lasso_select_mesh( if (ts->selectmode & SCE_SELECT_VERTEX) { if (bbsel) { - edbm_backbuf_check_and_select_verts(vc->em, sel_op); + data.is_changed = edbm_backbuf_check_and_select_verts(vc->em, sel_op); } else { mesh_foreachScreenVert(vc, do_lasso_select_mesh__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); @@ -694,7 +697,7 @@ static void do_lasso_select_mesh( if (ts->selectmode & SCE_SELECT_FACE) { if (bbsel) { - edbm_backbuf_check_and_select_faces(vc->em, sel_op); + data.is_changed = edbm_backbuf_check_and_select_faces(vc->em, sel_op); } else { mesh_foreachScreenFace(vc, do_lasso_select_mesh__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); @@ -702,7 +705,11 @@ static void do_lasso_select_mesh( } EDBM_backbuf_free(); - EDBM_selectmode_flush(vc->em); + + if (data.is_changed) { + EDBM_selectmode_flush(vc->em); + } + return data.is_changed; } static void do_lasso_select_curve__doSelect( @@ -716,6 +723,7 @@ static void do_lasso_select_curve__doSelect( const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT); + data->is_changed = true; } } else { @@ -727,6 +735,7 @@ static void do_lasso_select_curve__doSelect( SET_FLAG_FROM_TEST(bezt->f2, sel_op_result, SELECT); } bezt->f1 = bezt->f3 = bezt->f2; + data->is_changed = true; } else { char *flag_p = (&bezt->f1) + beztindex; @@ -734,12 +743,13 @@ static void do_lasso_select_curve__doSelect( const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(*flag_p, sel_op_result, SELECT); + data->is_changed = true; } } } } -static void do_lasso_select_curve(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) +static bool do_lasso_select_curve(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) { LassoSelectUserData data; rcti rect; @@ -750,12 +760,15 @@ static void do_lasso_select_curve(ViewContext *vc, const int mcords[][2], short if (SEL_OP_USE_PRE_DESELECT(sel_op)) { Curve *curve = (Curve *) vc->obedit->data; - ED_curve_deselect_all(curve->editnurb); + data.is_changed |= ED_curve_deselect_all(curve->editnurb); } ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ nurbs_foreachScreenVert(vc, do_lasso_select_curve__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - BKE_curve_nurb_vert_active_validate(vc->obedit->data); + if (data.is_changed) { + BKE_curve_nurb_vert_active_validate(vc->obedit->data); + } + return data.is_changed; } static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, const float screen_co[2]) @@ -768,9 +781,10 @@ static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, const const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT); + data->is_changed = true; } } -static void do_lasso_select_lattice(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) +static bool do_lasso_select_lattice(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) { LassoSelectUserData data; rcti rect; @@ -780,11 +794,12 @@ static void do_lasso_select_lattice(ViewContext *vc, const int mcords[][2], shor view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - ED_lattice_flags_set(vc->obedit, 0); + data.is_changed |= ED_lattice_flags_set(vc->obedit, 0); } ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ lattice_foreachScreenVert(vc, do_lasso_select_lattice__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + return data.is_changed; } static void do_lasso_select_armature__doSelectBone( @@ -830,7 +845,7 @@ static void do_lasso_select_armature__doSelectBone( } } -static void do_lasso_select_armature(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) +static bool do_lasso_select_armature(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) { LassoSelectUserData data; rcti rect; @@ -839,23 +854,24 @@ static void do_lasso_select_armature(ViewContext *vc, const int mcords[][2], sho view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - ED_armature_edit_deselect_all_visible(vc->obedit); + data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit); } bArmature *arm = vc->obedit->data; ED_armature_ebone_listbase_temp_clear(arm->edbo); + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + armature_foreachScreenBone(vc, do_lasso_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - data.is_changed = ED_armature_edit_select_op_from_tagged(vc->obedit->data, sel_op); + data.is_changed |= ED_armature_edit_select_op_from_tagged(vc->obedit->data, sel_op); if (data.is_changed) { WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obedit); } + return data.is_changed; } static void do_lasso_select_mball__doSelectElem(void *userData, struct MetaElem *ml, const float screen_co[2]) @@ -871,24 +887,26 @@ static void do_lasso_select_mball__doSelectElem(void *userData, struct MetaElem data->is_changed = true; } } -static void do_lasso_select_meta(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) +static bool do_lasso_select_meta(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) { LassoSelectUserData data; rcti rect; MetaBall *mb = (MetaBall *)vc->obedit->data; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - BKE_mball_deselect_all(mb); - } - BLI_lasso_boundbox(&rect, mcords, moves); view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + data.is_changed |= BKE_mball_deselect_all(mb); + } + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); mball_foreachScreenElem(vc, do_lasso_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + + return data.is_changed; } static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index)) @@ -904,7 +922,7 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv, data->is_changed = true; } } -static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) +static bool do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) { const bool use_zbuf = V3D_IS_ZBUF(vc->v3d); Object *ob = vc->obact; @@ -912,10 +930,12 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh rcti rect; if (me == NULL || me->totvert == 0) - return; + return false; + bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - paintvert_deselect_all_visible(ob, SEL_DESELECT, false); /* flush selection at the end */ + /* flush selection at the end */ + changed |= paintvert_deselect_all_visible(ob, SEL_DESELECT, false); } BLI_lasso_boundbox(&rect, mcords, moves); @@ -925,7 +945,7 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); - edbm_backbuf_check_and_select_verts_obmode(me, sel_op); + changed |= edbm_backbuf_check_and_select_verts_obmode(me, sel_op); EDBM_backbuf_free(); } @@ -938,26 +958,26 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh meshobject_foreachScreenVert(vc, do_lasso_select_meshobject__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + changed |= data.is_changed; } - if (SEL_OP_CAN_DESELECT(sel_op)) { - BKE_mesh_mselect_validate(me); + if (changed) { + if (SEL_OP_CAN_DESELECT(sel_op)) { + BKE_mesh_mselect_validate(me); + } + paintvert_flush_flags(ob); + paintvert_tag_select_update(vc->C, ob); } - paintvert_flush_flags(ob); - paintvert_tag_select_update(vc->C, ob); + return changed; } -static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) +static bool do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) { Object *ob = vc->obact; Mesh *me = ob->data; rcti rect; - if (me == NULL || me->totpoly == 0) - return; - - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - /* flush selection at the end */ - paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false); + if (me == NULL || me->totpoly == 0) { + return false; } bm_vertoffs = me->totpoly + 1; /* max index array */ @@ -965,11 +985,19 @@ static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], sh BLI_lasso_boundbox(&rect, mcords, moves); EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); - edbm_backbuf_check_and_select_tfaces(me, sel_op); + bool changed = false; + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + /* flush selection at the end */ + changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false); + } + changed |= edbm_backbuf_check_and_select_tfaces(me, sel_op); EDBM_backbuf_free(); - paintface_flush_flags(vc->C, ob, SELECT); + if (changed) { + paintface_flush_flags(vc->C, ob, SELECT); + } + return changed; } #if 0 @@ -981,6 +1009,7 @@ static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp s rcti rect; int node_cent[2]; float node_centf[2]; + bool changed = false; BLI_lasso_boundbox(&rect, mcords, moves); @@ -997,71 +1026,80 @@ static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp s const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(node->flag, sel_op_result, SELECT); + changed = true; } } - BIF_undo_push("Lasso select nodes"); + if (changed) { + BIF_undo_push("Lasso select nodes"); + } } #endif -static void view3d_lasso_select( +static bool view3d_lasso_select( bContext *C, ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) { Object *ob = CTX_data_active_object(C); + bool changed_multi = false; if (vc->obedit == NULL) { /* Object Mode */ if (BKE_paint_select_face_test(ob)) { - do_lasso_select_paintface(vc, mcords, moves, sel_op); + changed_multi = do_lasso_select_paintface(vc, mcords, moves, sel_op); } else if (BKE_paint_select_vert_test(ob)) { - do_lasso_select_paintvert(vc, mcords, moves, sel_op); + changed_multi = do_lasso_select_paintvert(vc, mcords, moves, sel_op); } else if (ob && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) { /* pass */ } else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) { - PE_lasso_select(C, mcords, moves, sel_op); + changed_multi = PE_lasso_select(C, mcords, moves, sel_op); } else if (ob && (ob->mode & OB_MODE_POSE)) { - do_lasso_select_pose(vc, mcords, moves, sel_op); + changed_multi = do_lasso_select_pose(vc, mcords, moves, sel_op); } else { - do_lasso_select_objects(vc, mcords, moves, sel_op); + changed_multi = do_lasso_select_objects(vc, mcords, moves, sel_op); } } else { /* Edit Mode */ FOREACH_OBJECT_IN_MODE_BEGIN (vc->view_layer, vc->v3d, ob->type, ob->mode, ob_iter) { ED_view3d_viewcontext_init_object(vc, ob_iter); + bool changed = false; switch (vc->obedit->type) { case OB_MESH: - do_lasso_select_mesh(vc, mcords, moves, sel_op); + changed = do_lasso_select_mesh(vc, mcords, moves, sel_op); break; case OB_CURVE: case OB_SURF: - do_lasso_select_curve(vc, mcords, moves, sel_op); + changed = do_lasso_select_curve(vc, mcords, moves, sel_op); break; case OB_LATTICE: - do_lasso_select_lattice(vc, mcords, moves, sel_op); + changed = do_lasso_select_lattice(vc, mcords, moves, sel_op); break; case OB_ARMATURE: - do_lasso_select_armature(vc, mcords, moves, sel_op); + changed = do_lasso_select_armature(vc, mcords, moves, sel_op); break; case OB_MBALL: - do_lasso_select_meta(vc, mcords, moves, sel_op); + changed = do_lasso_select_meta(vc, mcords, moves, sel_op); break; default: assert(!"lasso select on incorrect object type"); break; } - DEG_id_tag_update(vc->obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc->obedit->data); + if (changed) { + DEG_id_tag_update(vc->obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc->obedit->data); + changed_multi = true; + } } FOREACH_OBJECT_IN_MODE_END; } + return changed_multi; } @@ -1080,11 +1118,16 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op) ED_view3d_viewcontext_init(C, &vc); eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); - view3d_lasso_select(C, &vc, mcords, mcords_tot, sel_op); + bool changed_multi = view3d_lasso_select(C, &vc, mcords, mcords_tot, sel_op); MEM_freeN((void *)mcords); - return OPERATOR_FINISHED; + if (changed_multi) { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } return OPERATOR_PASS_THROUGH; } @@ -1957,10 +2000,12 @@ static bool ed_wpaint_vertex_select_pick( static int view3d_select_exec(bContext *C, wmOperator *op) { + Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); Object *obact = CTX_data_active_object(C); bool extend = RNA_boolean_get(op->ptr, "extend"); bool deselect = RNA_boolean_get(op->ptr, "deselect"); + bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all"); bool toggle = RNA_boolean_get(op->ptr, "toggle"); bool center = RNA_boolean_get(op->ptr, "center"); bool enumerate = RNA_boolean_get(op->ptr, "enumerate"); @@ -1990,36 +2035,85 @@ static int view3d_select_exec(bContext *C, wmOperator *op) } if (obedit && object == false) { - if (obedit->type == OB_MESH) + if (obedit->type == OB_MESH) { retval = EDBM_select_pick(C, location, extend, deselect, toggle); - else if (obedit->type == OB_ARMATURE) + if (!retval && deselect_all) { + retval = EDBM_mesh_deselect_all_multi(C); + } + } + else if (obedit->type == OB_ARMATURE) { retval = ED_armature_edit_select_pick(C, location, extend, deselect, toggle); - else if (obedit->type == OB_LATTICE) + if (!retval && deselect_all) { + retval = ED_armature_edit_deselect_all_visible_multi(C); + } + } + else if (obedit->type == OB_LATTICE) { retval = ED_lattice_select_pick(C, location, extend, deselect, toggle); - else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) + if (!retval && deselect_all) { + retval = ED_lattice_deselect_all_multi(C); + } + } + else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { retval = ED_curve_editnurb_select_pick(C, location, extend, deselect, toggle); - else if (obedit->type == OB_MBALL) + if (!retval && deselect_all) { + retval = ED_curve_deselect_all_multi(C); + } + } + else if (obedit->type == OB_MBALL) { retval = ED_mball_select_pick(C, location, extend, deselect, toggle); - else if (obedit->type == OB_FONT) + if (!retval && deselect_all) { + retval = ED_mball_deselect_all_multi(C); + } + } + else if (obedit->type == OB_FONT) { retval = ED_curve_editfont_select_pick(C, location, extend, deselect, toggle); + if (!retval && deselect_all) { + /* pass */ + } + } } - else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) - return PE_mouse_particles(C, location, extend, deselect, toggle); - else if (obact && BKE_paint_select_face_test(obact)) + else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) { + retval = PE_mouse_particles(C, location, extend, deselect, toggle); + if (!retval && deselect_all) { + retval = PE_deselect_all_visible(C); + } + } + else if (obact && BKE_paint_select_face_test(obact)) { retval = paintface_mouse_select(C, obact, location, extend, deselect, toggle); - else if (BKE_paint_select_vert_test(obact)) + if (!retval && deselect_all) { + retval = paintface_deselect_all_visible(C, CTX_data_active_object(C), SEL_DESELECT, false); + } + } + else if (BKE_paint_select_vert_test(obact)) { retval = ed_wpaint_vertex_select_pick(C, location, extend, deselect, toggle, obact); - else + if (!retval && deselect_all) { + retval = paintvert_deselect_all_visible(obact, SEL_DESELECT, false); + } + } + else { retval = ed_object_select_pick(C, location, extend, deselect, toggle, center, enumerate, object); + if (!retval && deselect_all) { + if (ED_pose_object_from_context(C)) { + retval = ED_pose_deselect_all_multi(C, SEL_DESELECT, false); + } + else { + retval = ED_object_base_deselect_all(CTX_data_view_layer(C), CTX_wm_view3d(C), SEL_DESELECT); + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + } + } + } /* passthrough allows tweaks * FINISHED to signal one operator worked * */ - if (retval) + if (retval) { + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED; - else + } + else { return OPERATOR_PASS_THROUGH; /* nothing selected, just passthrough */ + } } static int view3d_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) @@ -2048,6 +2142,8 @@ void VIEW3D_OT_select(wmOperatorType *ot) /* properties */ WM_operator_properties_mouse_select(ot); + prop = RNA_def_boolean(ot->srna, "deselect_all", 0, "Deselect", "Deselect all when nothing under the cursor"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); prop = RNA_def_boolean(ot->srna, "center", 0, "Center", "Use the object center when selecting, in editmode used to extend object selection"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); @@ -2109,9 +2205,10 @@ static void do_paintvert_box_select__doSelectVert(void *userData, MVert *mv, con const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT); + data->is_changed = true; } } -static int do_paintvert_box_select( +static bool do_paintvert_box_select( ViewContext *vc, const rcti *rect, const eSelectOp sel_op) { const bool use_zbuf = V3D_IS_ZBUF(vc->v3d); @@ -2126,8 +2223,9 @@ static int do_paintvert_box_select( return OPERATOR_CANCELLED; } + bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - paintvert_deselect_all_visible(vc->obact, SEL_DESELECT, false); + changed |= paintvert_deselect_all_visible(vc->obact, SEL_DESELECT, false); } if (use_zbuf) { @@ -2157,6 +2255,7 @@ static int do_paintvert_box_select( const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(mvert->flag, sel_op_result, SELECT); + changed = true; } } } @@ -2176,15 +2275,17 @@ static int do_paintvert_box_select( ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); meshobject_foreachScreenVert(vc, do_paintvert_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + changed |= data.is_changed; } - if (SEL_OP_CAN_DESELECT(sel_op)) { - BKE_mesh_mselect_validate(me); + if (changed) { + if (SEL_OP_CAN_DESELECT(sel_op)) { + BKE_mesh_mselect_validate(me); + } + paintvert_flush_flags(vc->obact); + paintvert_tag_select_update(vc->C, vc->obact); } - paintvert_flush_flags(vc->obact); - paintvert_tag_select_update(vc->C, vc->obact); - - return OPERATOR_FINISHED; + return changed; } static void do_nurbs_box_select__doSelect( @@ -2198,6 +2299,7 @@ static void do_nurbs_box_select__doSelect( const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT); + data->is_changed = true; } } else { @@ -2207,6 +2309,7 @@ static void do_nurbs_box_select__doSelect( const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(bezt->f2, sel_op_result, SELECT); + data->is_changed = true; } bezt->f1 = bezt->f3 = bezt->f2; } @@ -2216,11 +2319,12 @@ static void do_nurbs_box_select__doSelect( const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(*flag_p, sel_op_result, SELECT); + data->is_changed = true; } } } } -static int do_nurbs_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_op) +static bool do_nurbs_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_op) { BoxSelectUserData data; @@ -2228,14 +2332,14 @@ static int do_nurbs_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_ if (SEL_OP_USE_PRE_DESELECT(sel_op)) { Curve *curve = (Curve *) vc->obedit->data; - ED_curve_deselect_all(curve->editnurb); + data.is_changed |= ED_curve_deselect_all(curve->editnurb); } ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ nurbs_foreachScreenVert(vc, do_nurbs_box_select__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); BKE_curve_nurb_vert_active_validate(vc->obedit->data); - return OPERATOR_FINISHED; + return data.is_changed; } static void do_lattice_box_select__doSelect(void *userData, BPoint *bp, const float screen_co[2]) @@ -2246,22 +2350,23 @@ static void do_lattice_box_select__doSelect(void *userData, BPoint *bp, const fl const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT); + data->is_changed = true; } } -static int do_lattice_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_op) +static bool do_lattice_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_op) { BoxSelectUserData data; view3d_userdata_boxselect_init(&data, vc, rect, sel_op); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - ED_lattice_flags_set(vc->obedit, 0); + data.is_changed |= ED_lattice_flags_set(vc->obedit, 0); } ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ lattice_foreachScreenVert(vc, do_lattice_box_select__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - return OPERATOR_FINISHED; + return data.is_changed; } static void do_mesh_box_select__doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index)) @@ -2272,6 +2377,7 @@ static void do_mesh_box_select__doSelectVert(void *userData, BMVert *eve, const const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_vert_select_set(data->vc->em->bm, eve, sel_op_result); + data->is_changed = true; } } static void do_mesh_box_select__doSelectEdge_pass0( @@ -2286,6 +2392,7 @@ static void do_mesh_box_select__doSelectEdge_pass0( if (sel_op_result != -1) { BM_edge_select_set(data->vc->em->bm, eed, sel_op_result); data->is_done = true; + data->is_changed = true; } } static void do_mesh_box_select__doSelectEdge_pass1( @@ -2299,6 +2406,7 @@ static void do_mesh_box_select__doSelectEdge_pass1( const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_edge_select_set(data->vc->em->bm, eed, sel_op_result); + data->is_changed = true; } } static void do_mesh_box_select__doSelectFace(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index)) @@ -2309,9 +2417,10 @@ static void do_mesh_box_select__doSelectFace(void *userData, BMFace *efa, const const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_face_select_set(data->vc->em->bm, efa, sel_op_result); + data->is_changed = true; } } -static int do_mesh_box_select( +static bool do_mesh_box_select( ViewContext *vc, rcti *rect, const eSelectOp sel_op) { BoxSelectUserData data; @@ -2321,7 +2430,10 @@ static int do_mesh_box_select( view3d_userdata_boxselect_init(&data, vc, rect, sel_op); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT); + if (vc->em->bm->totvertsel) { + EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT); + data.is_changed = true; + } } /* for non zbuf projections, don't change the GL state */ @@ -2332,7 +2444,7 @@ static int do_mesh_box_select( if (ts->selectmode & SCE_SELECT_VERTEX) { if (bbsel) { - edbm_backbuf_check_and_select_verts(vc->em, sel_op); + data.is_changed = edbm_backbuf_check_and_select_verts(vc->em, sel_op); } else { mesh_foreachScreenVert(vc, do_mesh_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); @@ -2348,7 +2460,7 @@ static int do_mesh_box_select( if (ts->selectmode & SCE_SELECT_FACE) { if (bbsel) { - edbm_backbuf_check_and_select_faces(vc->em, sel_op); + data.is_changed = edbm_backbuf_check_and_select_faces(vc->em, sel_op); } else { mesh_foreachScreenFace(vc, do_mesh_box_select__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); @@ -2357,12 +2469,13 @@ static int do_mesh_box_select( EDBM_backbuf_free(); - EDBM_selectmode_flush(vc->em); - - return OPERATOR_FINISHED; + if (data.is_changed) { + EDBM_selectmode_flush(vc->em); + } + return data.is_changed; } -static int do_meta_box_select( +static bool do_meta_box_select( ViewContext *vc, const rcti *rect, const eSelectOp sel_op) { @@ -2370,6 +2483,7 @@ static int do_meta_box_select( MetaBall *mb = (MetaBall *)ob->data; MetaElem *ml; int a; + bool changed = false; uint buffer[MAXPICKBUF]; int hits; @@ -2379,7 +2493,7 @@ static int do_meta_box_select( VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - BKE_mball_deselect_all(mb); + changed |= BKE_mball_deselect_all(mb); } int metaelem_id = 0; @@ -2416,6 +2530,7 @@ static int do_meta_box_select( break; } } + const int flag_prev = ml->flag; if (is_inside_radius) { ml->flag |= MB_SCALE_RAD; } @@ -2430,12 +2545,13 @@ static int do_meta_box_select( if (sel_op_result != -1) { SET_FLAG_FROM_TEST(ml->flag, sel_op_result, SELECT); } + changed |= (flag_prev != ml->flag); } - return OPERATOR_FINISHED; + return changed; } -static int do_armature_box_select( +static bool do_armature_box_select( ViewContext *vc, const rcti *rect, const eSelectOp sel_op) { @@ -2449,16 +2565,15 @@ static int do_armature_box_select( vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(vc->view_layer, vc->v3d, &objects_len); + uint bases_len = 0; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc->view_layer, vc->v3d, &bases_len); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - ED_armature_edit_deselect_all_visible_multi(objects, objects_len); - changed = true; + changed |= ED_armature_edit_deselect_all_visible_multi_ex(bases, bases_len); } - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *obedit = bases[base_index]->object; obedit->id.tag &= ~LIB_TAG_DOIT; bArmature *arm = obedit->data; @@ -2474,23 +2589,23 @@ static int do_armature_box_select( } EditBone *ebone; - Object *obedit = ED_armature_object_and_ebone_from_select_buffer(objects, objects_len, select_id, &ebone); + Base *base_edit = ED_armature_base_and_ebone_from_select_buffer(bases, bases_len, select_id, &ebone); ebone->temp.i |= select_id & BONESEL_ANY; - obedit->id.tag |= LIB_TAG_DOIT; + base_edit->object->id.tag |= LIB_TAG_DOIT; } } - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *obedit = bases[base_index]->object; if (obedit->id.tag & LIB_TAG_DOIT) { obedit->id.tag &= ~LIB_TAG_DOIT; changed |= ED_armature_edit_select_op_from_tagged(obedit->data, sel_op); } } - MEM_freeN(objects); + MEM_freeN(bases); - return (hits > 0 || changed) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + return changed; } /** @@ -2519,10 +2634,9 @@ static int opengl_bone_select_buffer_cmp(const void *sel_a_p, const void *sel_b_ } } -static int do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const eSelectOp sel_op) +static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const eSelectOp sel_op) { View3D *v3d = vc->v3d; - bool changed = false; int totobj = MAXPICKBUF; /* XXX solve later */ /* selection buffer now has bones potentially too, so we add MAXPICKBUF */ @@ -2539,9 +2653,9 @@ static int do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const Base **bases = NULL; BLI_array_declare(bases); + bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - object_deselect_all_visible(vc->view_layer, vc->v3d); - changed = true; + changed |= object_deselect_all_visible(vc->view_layer, vc->v3d); } if ((hits == -1) && !SEL_OP_USE_OUTSIDE(sel_op)) { @@ -2589,14 +2703,11 @@ finally: if (changed) { DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene); - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; } + return changed; } -static int do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const eSelectOp sel_op) +static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const eSelectOp sel_op) { uint bases_len; Base **bases = do_pose_tag_select_op_prepare(vc, &bases_len); @@ -2669,14 +2780,14 @@ static int do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const eS } MEM_freeN(vbuffer); - return hits > 0 ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + return changed_multi; } static int view3d_box_select_exec(bContext *C, wmOperator *op) { ViewContext vc; rcti rect; - int ret = OPERATOR_CANCELLED; + bool changed_multi = false; view3d_operator_needs_opengl(C); @@ -2690,41 +2801,42 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) FOREACH_OBJECT_IN_MODE_BEGIN (vc.view_layer, vc.v3d, vc.obedit->type, vc.obedit->mode, ob_iter) { ED_view3d_viewcontext_init_object(&vc, ob_iter); + bool changed = false; switch (vc.obedit->type) { case OB_MESH: vc.em = BKE_editmesh_from_object(vc.obedit); - ret |= do_mesh_box_select(&vc, &rect, sel_op); - if (ret & OPERATOR_FINISHED) { + changed = do_mesh_box_select(&vc, &rect, sel_op); + if (changed) { DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); } break; case OB_CURVE: case OB_SURF: - ret |= do_nurbs_box_select(&vc, &rect, sel_op); - if (ret & OPERATOR_FINISHED) { + changed = do_nurbs_box_select(&vc, &rect, sel_op); + if (changed) { DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); } break; case OB_MBALL: - ret |= do_meta_box_select(&vc, &rect, sel_op); - if (ret & OPERATOR_FINISHED) { + changed = do_meta_box_select(&vc, &rect, sel_op); + if (changed) { DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); } break; case OB_ARMATURE: - ret |= do_armature_box_select(&vc, &rect, sel_op); - if (ret & OPERATOR_FINISHED) { + changed = do_armature_box_select(&vc, &rect, sel_op); + if (changed) { DEG_id_tag_update(&vc.obedit->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit); } break; case OB_LATTICE: - ret |= do_lattice_box_select(&vc, &rect, sel_op); - if (ret & OPERATOR_FINISHED) { + changed = do_lattice_box_select(&vc, &rect, sel_op); + if (changed) { DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); } @@ -2733,39 +2845,38 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) assert(!"box select on incorrect object type"); break; } + changed_multi |= changed; } FOREACH_OBJECT_IN_MODE_END; } else { /* no editmode, unified for bones and objects */ if (vc.obact && vc.obact->mode & OB_MODE_SCULPT) { /* XXX, this is not selection, could be it's own operator. */ - ret |= ED_sculpt_mask_box_select(C, &vc, &rect, sel_op == SEL_OP_ADD ? true : false); + changed_multi = ED_sculpt_mask_box_select(C, &vc, &rect, sel_op == SEL_OP_ADD ? true : false); } else if (vc.obact && BKE_paint_select_face_test(vc.obact)) { - ret |= do_paintface_box_select(&vc, &rect, sel_op); + changed_multi = do_paintface_box_select(&vc, &rect, sel_op); } else if (vc.obact && BKE_paint_select_vert_test(vc.obact)) { - ret |= do_paintvert_box_select(&vc, &rect, sel_op); + changed_multi = do_paintvert_box_select(&vc, &rect, sel_op); } else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) { - ret |= PE_box_select(C, &rect, sel_op); + changed_multi = PE_box_select(C, &rect, sel_op); } else if (vc.obact && vc.obact->mode & OB_MODE_POSE) { - ret |= do_pose_box_select(C, &vc, &rect, sel_op); + changed_multi = do_pose_box_select(C, &vc, &rect, sel_op); } else { /* object mode with none active */ - ret |= do_object_box_select(C, &vc, &rect, sel_op); + changed_multi = do_object_box_select(C, &vc, &rect, sel_op); } } - if (ret & OPERATOR_FINISHED) { - ret = OPERATOR_FINISHED; + if (changed_multi) { + return OPERATOR_FINISHED; } else { - ret = OPERATOR_CANCELLED; + return OPERATOR_CANCELLED; } - - return ret; } void VIEW3D_OT_select_box(wmOperatorType *ot) @@ -2863,8 +2974,10 @@ static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT); - changed = true; + if (vc->em->bm->totvertsel) { + EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT); + changed = true; + } } const bool select = (sel_op != SEL_OP_SUB); @@ -2907,7 +3020,6 @@ static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval if (changed) { EDBM_selectmode_flush(vc->em); } - return changed; } @@ -2917,11 +3029,11 @@ static bool paint_facesel_circle_select(ViewContext *vc, const eSelectOp sel_op, Object *ob = vc->obact; Mesh *me = ob->data; bool bbsel; - bool changed = false; + bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false); - changed = true; + /* flush selection at the end */ + changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false); } bm_vertoffs = me->totpoly + 1; /* max index array */ @@ -2943,6 +3055,7 @@ static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv, if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT); + data->is_changed = true; } } static bool paint_vertsel_circle_select(ViewContext *vc, const eSelectOp sel_op, const int mval[2], float rad) @@ -2953,11 +3066,10 @@ static bool paint_vertsel_circle_select(ViewContext *vc, const eSelectOp sel_op, Mesh *me = ob->data; bool bbsel; /* CircleSelectUserData data = {NULL}; */ /* UNUSED */ - bool changed = false; + bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - paintvert_deselect_all_visible(ob, SEL_DESELECT, false); /* flush selection at the end */ - changed = true; + changed |= paintvert_deselect_all_visible(ob, SEL_DESELECT, false); /* flush selection at the end */ } const bool select = (sel_op != SEL_OP_SUB); @@ -3027,8 +3139,7 @@ static bool nurbscurve_circle_select(ViewContext *vc, const eSelectOp sel_op, co bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { Curve *curve = vc->obedit->data; - ED_curve_deselect_all(curve->editnurb); - changed = true; + changed |= ED_curve_deselect_all(curve->editnurb); } const bool select = (sel_op != SEL_OP_SUB); @@ -3054,20 +3165,19 @@ static void latticecurve_circle_doSelect(void *userData, BPoint *bp, const float static bool lattice_circle_select(ViewContext *vc, const eSelectOp sel_op, const int mval[2], float rad) { CircleSelectUserData data; - bool changed = false; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - Curve *curve = vc->obedit->data; - ED_curve_deselect_all(curve->editnurb); - changed = true; - } const bool select = (sel_op != SEL_OP_SUB); view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + Curve *curve = vc->obedit->data; + data.is_changed |= ED_curve_deselect_all(curve->editnurb); + } ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ + lattice_foreachScreenVert(vc, latticecurve_circle_doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - return changed || data.is_changed; + return data.is_changed; } @@ -3133,23 +3243,22 @@ static bool pose_circle_select(ViewContext *vc, const eSelectOp sel_op, const in { BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); CircleSelectUserData data; - bool changed = false; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - changed |= ED_pose_deselect_all(vc->obact, SEL_DESELECT, false); - } const bool select = (sel_op != SEL_OP_SUB); view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + data.is_changed |= ED_pose_deselect_all(vc->obact, SEL_DESELECT, false); + } + ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */ pose_foreachScreenBone(vc, do_circle_select_pose__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - changed |= data.is_changed; - if (changed) { + if (data.is_changed) { ED_pose_bone_select_tag_update(vc->obact); } - return changed; + return data.is_changed; } static bool armature_circle_doSelectJoint(void *userData, EditBone *ebone, const float screen_co[2], bool head) @@ -3222,15 +3331,14 @@ static bool armature_circle_select(ViewContext *vc, const eSelectOp sel_op, cons CircleSelectUserData data; bArmature *arm = vc->obedit->data; - bool changed = false; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - ED_armature_edit_deselect_all_visible(vc->obedit); - changed = true; - } const bool select = (sel_op != SEL_OP_SUB); view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit); + } + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); armature_foreachScreenBone(vc, do_circle_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT); @@ -3240,8 +3348,7 @@ static bool armature_circle_select(ViewContext *vc, const eSelectOp sel_op, cons ED_armature_edit_validate_active(arm); WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obedit); } - changed |= data.is_changed; - return changed; + return data.is_changed; } static void do_circle_select_mball__doSelectElem(void *userData, struct MetaElem *ml, const float screen_co[2]) @@ -3258,20 +3365,18 @@ static bool mball_circle_select(ViewContext *vc, const eSelectOp sel_op, const i { CircleSelectUserData data; - bool changed = false; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - BKE_mball_deselect_all(vc->obedit->data); - changed = true; - } const bool select = (sel_op != SEL_OP_SUB); view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + data.is_changed |= BKE_mball_deselect_all(vc->obedit->data); + } + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); mball_foreachScreenElem(vc, do_circle_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - changed |= data.is_changed; - return changed; + return data.is_changed; } /** Callbacks for circle selection in Editmode */ @@ -3309,9 +3414,7 @@ static bool object_circle_select(ViewContext *vc, const eSelectOp sel_op, const bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - if (object_deselect_all_visible(vc->view_layer, vc->v3d)) { - changed = true; - } + changed |= object_deselect_all_visible(vc->view_layer, vc->v3d); } const bool select = (sel_op != SEL_OP_SUB); const int select_flag = select ? BASE_SELECTED : 0; diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index d432209575b..1ee81b56636 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -490,6 +490,10 @@ typedef enum eBezTriple_KeyframeType { /* checks if the given BezTriple is selected */ #define BEZT_ISSEL_ANY(bezt) \ (((bezt)->f2 & SELECT) || ((bezt)->f1 & SELECT) || ((bezt)->f3 & SELECT)) +#define BEZT_ISSEL_ALL(bezt) \ + (((bezt)->f2 & SELECT) && ((bezt)->f1 & SELECT) && ((bezt)->f3 & SELECT)) +#define BEZT_ISSEL_ALL_HIDDENHANDLES(v3d, bezt) \ + ((((v3d) != NULL) && ((v3d)->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) ? (bezt)->f2 & SELECT : BEZT_ISSEL_ALL(bezt)) #define BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt) \ ((((v3d) != NULL) && ((v3d)->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) ? (bezt)->f2 & SELECT : BEZT_ISSEL_ANY(bezt)) -- cgit v1.2.3