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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/space_view3d/view3d_select.c')
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c1585
1 files changed, 997 insertions, 588 deletions
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index d8c21da48a4..a3bd31423e8 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -44,9 +44,11 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_tracking_types.h"
+#include "DNA_gpencil_types.h"
#include "MEM_guardedalloc.h"
+#include "BLI_array.h"
#include "BLI_math.h"
#include "BLI_lasso_2d.h"
#include "BLI_rect.h"
@@ -55,6 +57,10 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#ifdef __BIG_ENDIAN__
+# include "BLI_endian_switch.h"
+#endif
+
/* vertex box select */
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -63,16 +69,17 @@
#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
+#include "BKE_layer.h"
#include "BKE_mball.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_editmesh.h"
+#include "BKE_scene.h"
#include "BKE_tracking.h"
+#include "BKE_workspace.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
+#include "DEG_depsgraph.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -88,12 +95,16 @@
#include "ED_mesh.h"
#include "ED_object.h"
#include "ED_screen.h"
+#include "ED_select_utils.h"
#include "ED_sculpt.h"
#include "ED_mball.h"
+#include "ED_gpencil.h"
#include "UI_interface.h"
#include "GPU_draw.h"
+#include "GPU_glew.h"
+#include "GPU_matrix.h"
#include "view3d_intern.h" /* own include */
@@ -110,7 +121,9 @@ void ED_view3d_viewcontext_init(bContext *C, ViewContext *vc)
memset(vc, 0, sizeof(ViewContext));
vc->ar = CTX_wm_region(C);
vc->bmain = CTX_data_main(C);
+ vc->depsgraph = CTX_data_depsgraph(C);
vc->scene = CTX_data_scene(C);
+ vc->view_layer = CTX_data_view_layer(C);
vc->v3d = CTX_wm_view3d(C);
vc->win = CTX_wm_window(C);
vc->rv3d = CTX_wm_region_view3d(C);
@@ -118,39 +131,26 @@ void ED_view3d_viewcontext_init(bContext *C, ViewContext *vc)
vc->obedit = CTX_data_edit_object(C);
}
-/*
- * ob == NULL if you want global matrices
- * */
-void view3d_get_transformation(const ARegion *ar, RegionView3D *rv3d, Object *ob, bglMats *mats)
+void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact)
{
- float cpy[4][4];
- int i, j;
+ vc->obact = obact;
+ if (vc->obedit) {
+ BLI_assert(BKE_object_is_in_editmode(obact));
+ vc->obedit = obact;
+ /* previous selections are now invalid. */
+ vc->v3d->flag |= V3D_INVALID_BACKBUF;
- if (ob) {
- mul_m4_m4m4(cpy, rv3d->viewmat, ob->obmat);
- }
- else {
- copy_m4_m4(cpy, rv3d->viewmat);
- }
-
- for (i = 0; i < 4; ++i) {
- for (j = 0; j < 4; ++j) {
- mats->projection[i * 4 + j] = rv3d->winmat[i][j];
- mats->modelview[i * 4 + j] = cpy[i][j];
+ if (vc->em) {
+ vc->em = BKE_editmesh_from_object(vc->obedit);
}
}
-
- mats->viewport[0] = ar->winrct.xmin;
- mats->viewport[1] = ar->winrct.ymin;
- mats->viewport[2] = ar->winx;
- mats->viewport[3] = ar->winy;
}
/* ********************** view3d_select: selection manipulations ********************* */
/* local prototypes */
-static void edbm_backbuf_check_and_select_verts(BMEditMesh *em, const bool select)
+static void edbm_backbuf_check_and_select_verts(BMEditMesh *em, const eSelectOp sel_op)
{
BMVert *eve;
BMIter iter;
@@ -158,15 +158,18 @@ static void edbm_backbuf_check_and_select_verts(BMEditMesh *em, const bool selec
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- if (EDBM_backbuf_check(index)) {
- BM_vert_select_set(em->bm, eve, select);
+ const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT);
+ const bool is_inside = EDBM_backbuf_check(index);
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ BM_vert_select_set(em->bm, eve, sel_op_result);
}
}
index++;
}
}
-static void edbm_backbuf_check_and_select_edges(BMEditMesh *em, const bool select)
+static void edbm_backbuf_check_and_select_edges(BMEditMesh *em, const eSelectOp sel_op)
{
BMEdge *eed;
BMIter iter;
@@ -174,15 +177,18 @@ static void edbm_backbuf_check_and_select_edges(BMEditMesh *em, const bool selec
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- if (EDBM_backbuf_check(index)) {
- BM_edge_select_set(em->bm, eed, select);
+ const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
+ const bool is_inside = EDBM_backbuf_check(index);
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ BM_edge_select_set(em->bm, eed, sel_op_result);
}
}
index++;
}
}
-static void edbm_backbuf_check_and_select_faces(BMEditMesh *em, const bool select)
+static void edbm_backbuf_check_and_select_faces(BMEditMesh *em, const eSelectOp sel_op)
{
BMFace *efa;
BMIter iter;
@@ -190,26 +196,31 @@ static void edbm_backbuf_check_and_select_faces(BMEditMesh *em, const bool selec
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- if (EDBM_backbuf_check(index)) {
- BM_face_select_set(em->bm, efa, select);
+ const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT);
+ const bool is_inside = EDBM_backbuf_check(index);
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ BM_face_select_set(em->bm, efa, sel_op_result);
}
}
index++;
}
}
-
/* object mode, edbm_ prefix is confusing here, rename? */
-static void edbm_backbuf_check_and_select_verts_obmode(Mesh *me, const bool select)
+static void edbm_backbuf_check_and_select_verts_obmode(Mesh *me, const eSelectOp sel_op)
{
MVert *mv = me->mvert;
unsigned int index;
if (mv) {
for (index = 1; index <= me->totvert; index++, mv++) {
- if (EDBM_backbuf_check(index)) {
- if (!(mv->flag & ME_HIDE)) {
- mv->flag = select ? (mv->flag | SELECT) : (mv->flag & ~SELECT);
+ if (!(mv->flag & ME_HIDE)) {
+ const bool is_select = mv->flag & SELECT;
+ const bool is_inside = EDBM_backbuf_check(index);
+ 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(mv->flag, sel_op_result, SELECT);
}
}
}
@@ -217,15 +228,20 @@ static void edbm_backbuf_check_and_select_verts_obmode(Mesh *me, const bool sele
}
/* object mode, edbm_ prefix is confusing here, rename? */
-static void edbm_backbuf_check_and_select_tfaces(Mesh *me, const bool select)
+static void edbm_backbuf_check_and_select_tfaces(Mesh *me, const eSelectOp sel_op)
{
MPoly *mpoly = me->mpoly;
unsigned int index;
if (mpoly) {
for (index = 1; index <= me->totpoly; index++, mpoly++) {
- if (EDBM_backbuf_check(index)) {
- mpoly->flag = select ? (mpoly->flag | ME_FACE_SEL) : (mpoly->flag & ~ME_FACE_SEL);
+ if (!(mpoly->flag & ME_HIDE)) {
+ const bool is_select = mpoly->flag & ME_FACE_SEL;
+ const bool is_inside = EDBM_backbuf_check(index);
+ 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);
+ }
}
}
}
@@ -240,7 +256,7 @@ typedef struct LassoSelectUserData {
rctf _rect_fl;
const int (*mcords)[2];
int moves;
- bool select;
+ eSelectOp sel_op;
/* runtime */
int pass;
@@ -251,7 +267,7 @@ typedef struct LassoSelectUserData {
static void view3d_userdata_lassoselect_init(
LassoSelectUserData *r_data,
ViewContext *vc, const rcti *rect, const int (*mcords)[2],
- const int moves, const bool select)
+ const int moves, const eSelectOp sel_op)
{
r_data->vc = vc;
@@ -261,7 +277,7 @@ static void view3d_userdata_lassoselect_init(
r_data->mcords = mcords;
r_data->moves = moves;
- r_data->select = select;
+ r_data->sel_op = sel_op;
/* runtime */
r_data->pass = 0;
@@ -326,7 +342,7 @@ static bool edge_inside_rect(const rctf *rect, const float v1[2], const float v2
return 1;
}
-static void do_lasso_select_pose__doSelectBone(
+static void do_lasso_select_pose__do_tag(
void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2])
{
LassoSelectUserData *data = userData;
@@ -336,26 +352,21 @@ static void do_lasso_select_pose__doSelectBone(
bool is_point_done = false;
int points_proj_tot = 0;
- const int x0 = screen_co_a[0];
- const int y0 = screen_co_a[1];
- const int x1 = screen_co_b[0];
- const int y1 = screen_co_b[1];
-
/* project head location to screenspace */
- if (x0 != IS_CLIPPED) {
+ if (screen_co_a[0] != IS_CLIPPED) {
points_proj_tot++;
- if (BLI_rcti_isect_pt(data->rect, x0, y0) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, x0, y0, INT_MAX))
+ if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) &&
+ BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), INT_MAX))
{
is_point_done = true;
}
}
/* project tail location to screenspace */
- if (x1 != IS_CLIPPED) {
+ if (screen_co_b[0] != IS_CLIPPED) {
points_proj_tot++;
- if (BLI_rcti_isect_pt(data->rect, x1, y1) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, x1, y1, INT_MAX))
+ if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) &&
+ BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), INT_MAX))
{
is_point_done = true;
}
@@ -364,16 +375,14 @@ static void do_lasso_select_pose__doSelectBone(
/* if one of points selected, we skip the bone itself */
if ((is_point_done == true) ||
((is_point_done == false) && (points_proj_tot == 2) &&
- BLI_lasso_is_edge_inside(data->mcords, data->moves, x0, y0, x1, y1, INT_MAX)))
+ BLI_lasso_is_edge_inside(data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX)))
{
- if (data->select) pchan->bone->flag |= BONE_SELECTED;
- else pchan->bone->flag &= ~BONE_SELECTED;
- data->is_changed = true;
+ pchan->bone->flag |= BONE_DONE;
}
data->is_changed |= is_point_done;
}
}
-static void do_lasso_select_pose(ViewContext *vc, Object *ob, const int mcords[][2], short moves, const bool select)
+static void do_lasso_tag_pose(ViewContext *vc, Object *ob, const int mcords[][2], short moves)
{
ViewContext vc_tmp;
LassoSelectUserData data;
@@ -388,106 +397,217 @@ static void do_lasso_select_pose(ViewContext *vc, Object *ob, const int mcords[]
BLI_lasso_boundbox(&rect, mcords, moves);
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
-
- ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, 0);
- pose_foreachScreenBone(&vc_tmp, do_lasso_select_pose__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ ED_view3d_init_mats_rv3d(vc_tmp.obact, vc->rv3d);
- if (data.is_changed) {
- bArmature *arm = ob->data;
- if (arm->flag & ARM_HAS_VIZ_DEPS) {
- /* mask modifier ('armature' mode), etc. */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- }
- }
+ pose_foreachScreenBone(&vc_tmp, do_lasso_select_pose__do_tag, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
-static void object_deselect_all_visible(Scene *scene, View3D *v3d)
+static void object_deselect_all_visible(ViewLayer *view_layer)
{
Base *base;
- for (base = scene->base.first; base; base = base->next) {
- if (BASE_SELECTABLE(v3d, base)) {
- ED_base_object_select(base, BA_DESELECT);
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_SELECTABLE(base)) {
+ ED_object_base_select(base, BA_DESELECT);
}
}
}
static void do_lasso_select_objects(
ViewContext *vc, const int mcords[][2], const short moves,
- const bool extend, const bool select)
+ const eSelectOp sel_op)
{
Base *base;
- if (extend == false && select)
- object_deselect_all_visible(vc->scene, vc->v3d);
-
- for (base = vc->scene->base.first; base; base = base->next) {
- if (BASE_SELECTABLE(vc->v3d, base)) { /* use this to avoid un-needed lasso lookups */
- if (ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK) {
- if (BLI_lasso_is_point_inside(mcords, moves, base->sx, base->sy, IS_CLIPPED)) {
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ object_deselect_all_visible(vc->view_layer);
+ }
- ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT);
- base->object->flag = base->flag;
- }
- }
- if (vc->obact == base->object && (base->object->mode & OB_MODE_POSE)) {
- do_lasso_select_pose(vc, base->object, mcords, moves, select);
+ bool changed = false;
+ for (base = vc->view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_SELECTABLE(base)) { /* use this to avoid un-needed lasso lookups */
+ const bool is_select = base->flag & BASE_SELECTED;
+ const bool is_inside = (
+ (ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK) &&
+ BLI_lasso_is_point_inside(mcords, moves, base->sx, base->sy, IS_CLIPPED));
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ ED_object_base_select(base, sel_op_result ? BA_SELECT : BA_DESELECT);
+ changed = true;
}
}
}
+
+ if (changed) {
+ DEG_id_tag_update(&vc->scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, vc->scene);
+ }
}
-static void do_lasso_select_mesh__doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index))
-{
- LassoSelectUserData *data = userData;
- if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED))
- {
- BM_vert_select_set(data->vc->em->bm, eve, data->select);
+/**
+ * Use for lasso & border select.
+ */
+static Base **do_pose_tag_select_op_prepare(ViewContext *vc, uint *r_bases_len)
+{
+ Base **bases = NULL;
+ BLI_array_declare(bases);
+ FOREACH_BASE_IN_MODE_BEGIN (vc->view_layer, OB_MODE_POSE, base_iter) {
+ Object *ob_iter = base_iter->object;
+ bArmature *arm = ob_iter->data;
+ for (bPoseChannel *pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) {
+ Bone *bone = pchan->bone;
+ bone->flag &= ~BONE_DONE;
+ }
+ arm->id.tag |= LIB_TAG_DOIT;
+ ob_iter->id.tag &= ~LIB_TAG_DOIT;
+ BLI_array_append(bases, base_iter);
}
+ FOREACH_BASE_IN_MODE_END;
+ *r_bases_len = BLI_array_len(bases);
+ return bases;
}
-static void do_lasso_select_mesh__doSelectEdge(
- void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
-{
- LassoSelectUserData *data = userData;
- if (EDBM_backbuf_check(bm_solidoffs + index)) {
- const int x0 = screen_co_a[0];
- const int y0 = screen_co_a[1];
- const int x1 = screen_co_b[0];
- const int y1 = screen_co_b[1];
+static bool do_pose_tag_select_op_exec(Base **bases, const uint bases_len, const eSelectOp sel_op)
+{
+ bool changed_multi = false;
- if (data->pass == 0) {
- if (edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, x0, y0, IS_CLIPPED) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, x1, y1, IS_CLIPPED))
- {
- BM_edge_select_set(data->vc->em->bm, eed, data->select);
- data->is_done = true;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ for (int i = 0; i < bases_len; i++) {
+ Base *base_iter = bases[i];
+ Object *ob_iter = base_iter->object;
+ if (ED_pose_deselect_all(ob_iter, SEL_DESELECT, false)) {
+ ED_pose_bone_select_tag_update(ob_iter);
+ changed_multi = true;
}
}
+ }
+
+ for (int i = 0; i < bases_len; i++) {
+ Base *base_iter = bases[i];
+ Object *ob_iter = base_iter->object;
+ bArmature *arm = ob_iter->data;
+
+ /* Don't handle twice. */
+ if (arm->id.tag & LIB_TAG_DOIT) {
+ arm->id.tag &= ~LIB_TAG_DOIT;
+ }
else {
- if (BLI_lasso_is_edge_inside(data->mcords, data->moves, x0, y0, x1, y1, IS_CLIPPED)) {
- BM_edge_select_set(data->vc->em->bm, eed, data->select);
+ continue;
+ }
+
+ bool changed = true;
+ for (bPoseChannel *pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) {
+ Bone *bone = pchan->bone;
+ if ((bone->flag & BONE_UNSELECTABLE) == 0) {
+ const bool is_select = bone->flag & BONE_SELECTED;
+ const bool is_inside = bone->flag & BONE_DONE;
+ 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(bone->flag, sel_op_result, BONE_SELECTED);
+ if (sel_op_result == 0) {
+ if (arm->act_bone == bone) {
+ arm->act_bone = NULL;
+ }
+ }
+ changed = true;
+ }
}
}
+ if (changed) {
+ ED_pose_bone_select_tag_update(ob_iter);
+ changed_multi = true;
+ }
}
+ return changed_multi;
}
-static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
+
+static void do_lasso_select_pose(
+ ViewContext *vc, const int mcords[][2], const short moves,
+ const eSelectOp sel_op)
+{
+ uint bases_len;
+ Base **bases = do_pose_tag_select_op_prepare(vc, &bases_len);
+
+ for (int i = 0; i < bases_len; i++) {
+ Base *base_iter = bases[i];
+ Object *ob_iter = base_iter->object;
+ do_lasso_tag_pose(vc, ob_iter, mcords, moves);
+ }
+
+ const bool changed_multi = do_pose_tag_select_op_exec(bases, bases_len, sel_op);
+ if (changed_multi) {
+ DEG_id_tag_update(&vc->scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, vc->scene);
+ }
+
+ if (bases != NULL) {
+ MEM_freeN(bases);
+ }
+}
+
+static void do_lasso_select_mesh__doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index))
+{
+ LassoSelectUserData *data = userData;
+ const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT);
+ const bool is_inside = (
+ BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
+ BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED));
+ 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);
+ }
+}
+static void do_lasso_select_mesh__doSelectEdge_pass0(
+ void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
{
LassoSelectUserData *data = userData;
+ const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
+ const bool is_inside = (
+ EDBM_backbuf_check(bm_solidoffs + index) &&
+ edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) &&
+ BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), IS_CLIPPED) &&
+ BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), IS_CLIPPED));
+ 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_done = true;
+ }
+}
+static void do_lasso_select_mesh__doSelectEdge_pass1(
+ void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
+{
+ LassoSelectUserData *data = userData;
+ const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
+ const bool is_inside = (
+ EDBM_backbuf_check(bm_solidoffs + index) &&
+ BLI_lasso_is_edge_inside(
+ data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), IS_CLIPPED));
+ 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);
+ }
+}
- if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED))
- {
- BM_face_select_set(data->vc->em->bm, efa, data->select);
+static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
+{
+ LassoSelectUserData *data = userData;
+ const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT);
+ const bool is_inside = (
+ BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
+ BLI_lasso_is_point_inside(
+ data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED));
+ 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);
}
}
-static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
+static void do_lasso_select_mesh(
+ ViewContext *vc,
+ const int mcords[][2], short moves, const eSelectOp sel_op)
{
LassoSelectUserData data;
ToolSettings *ts = vc->scene->toolsettings;
@@ -499,20 +619,21 @@ static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short m
BLI_lasso_boundbox(&rect, mcords, moves);
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
- if (extend == false && select)
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT);
+ }
/* for non zbuf projections, don't change the GL state */
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- glLoadMatrixf(vc->rv3d->viewmat);
+ GPU_matrix_set(vc->rv3d->viewmat);
bbsel = EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
if (ts->selectmode & SCE_SELECT_VERTEX) {
if (bbsel) {
- edbm_backbuf_check_and_select_verts(vc->em, select);
+ 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);
@@ -520,18 +641,15 @@ static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short m
}
if (ts->selectmode & SCE_SELECT_EDGE) {
/* Does both bbsel and non-bbsel versions (need screen cos for both) */
- data.pass = 0;
- mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
-
+ mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge_pass0, &data, V3D_PROJ_TEST_CLIP_NEAR);
if (data.is_done == false) {
- data.pass = 1;
- mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge_pass1, &data, V3D_PROJ_TEST_CLIP_NEAR);
}
}
if (ts->selectmode & SCE_SELECT_FACE) {
if (bbsel) {
- edbm_backbuf_check_and_select_faces(vc->em, select);
+ 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);
@@ -546,43 +664,46 @@ static void do_lasso_select_curve__doSelect(
void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
{
LassoSelectUserData *data = userData;
- Object *obedit = data->vc->obedit;
- Curve *cu = (Curve *)obedit->data;
- if (BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)) {
- if (bp) {
- bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
+ const bool is_inside = BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED);
+ if (bp) {
+ const bool is_select = bp->f1 & SELECT;
+ 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);
}
- else {
- if (cu->drawflag & CU_HIDE_HANDLES) {
- /* can only be (beztindex == 0) here since handles are hidden */
- bezt->f1 = bezt->f2 = bezt->f3 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
+ }
+ else {
+ if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
+ /* can only be (beztindex == 0) here since handles are hidden */
+ const bool is_select = bezt->f2 & SELECT;
+ 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);
}
- else {
- if (beztindex == 0) {
- bezt->f1 = data->select ? (bezt->f1 | SELECT) : (bezt->f1 & ~SELECT);
- }
- else if (beztindex == 1) {
- bezt->f2 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
- }
- else {
- bezt->f3 = data->select ? (bezt->f3 | SELECT) : (bezt->f3 & ~SELECT);
- }
+ bezt->f1 = bezt->f3 = bezt->f2;
+ }
+ else {
+ char *flag_p = (&bezt->f1) + beztindex;
+ const bool is_select = *flag_p & SELECT;
+ 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);
}
}
}
}
-static void do_lasso_select_curve(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
+static void do_lasso_select_curve(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op)
{
LassoSelectUserData data;
rcti rect;
BLI_lasso_boundbox(&rect, mcords, moves);
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
- if (extend == false && select) {
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
Curve *curve = (Curve *) vc->obedit->data;
ED_curve_deselect_all(curve->editnurb);
}
@@ -595,74 +716,83 @@ static void do_lasso_select_curve(ViewContext *vc, const int mcords[][2], short
static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, const float screen_co[2])
{
LassoSelectUserData *data = userData;
-
- if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED))
- {
- bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
+ const bool is_select = bp->f1 | SELECT;
+ const bool is_inside = (
+ BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
+ BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED));
+ 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);
}
}
-static void do_lasso_select_lattice(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
+static void do_lasso_select_lattice(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op)
{
LassoSelectUserData data;
rcti rect;
BLI_lasso_boundbox(&rect, mcords, moves);
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
- if (extend == false && select)
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
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);
}
-static void do_lasso_select_armature__doSelectBone(
- void *userData, struct EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2])
+static void do_lasso_select_armature__doSelectBone(void *userData, struct EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2])
{
LassoSelectUserData *data = userData;
bArmature *arm = data->vc->obedit->data;
-
- if (data->select ? EBONE_SELECTABLE(arm, ebone) : EBONE_VISIBLE(arm, ebone)) {
+ if (EBONE_VISIBLE(arm, ebone)) {
bool is_point_done = false;
int points_proj_tot = 0;
- const int x0 = screen_co_a[0];
- const int y0 = screen_co_a[1];
- const int x1 = screen_co_b[0];
- const int y1 = screen_co_b[1];
-
/* project head location to screenspace */
- if (x0 != IS_CLIPPED) {
+ if (screen_co_a[0] != IS_CLIPPED) {
points_proj_tot++;
- if (BLI_rcti_isect_pt(data->rect, x0, y0) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, x0, y0, INT_MAX))
- {
- is_point_done = true;
- if (data->select) ebone->flag |= BONE_ROOTSEL;
- else ebone->flag &= ~BONE_ROOTSEL;
+ const bool is_select = ebone->flag & BONE_ROOTSEL;
+ const bool is_inside = (
+ BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) &&
+ BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), INT_MAX));
+ const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
+ SET_FLAG_FROM_TEST(ebone->flag, sel_op_result, BONE_ROOTSEL);
+ }
}
+ is_point_done |= is_inside;
}
/* project tail location to screenspace */
- if (x1 != IS_CLIPPED) {
+ if (screen_co_b[0] != IS_CLIPPED) {
points_proj_tot++;
- if (BLI_rcti_isect_pt(data->rect, x1, y1) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, x1, y1, INT_MAX))
- {
- is_point_done = true;
- if (data->select) ebone->flag |= BONE_TIPSEL;
- else ebone->flag &= ~BONE_TIPSEL;
+ const bool is_select = ebone->flag & BONE_TIPSEL;
+ const bool is_inside = (
+ BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) &&
+ BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), INT_MAX));
+ const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
+ SET_FLAG_FROM_TEST(ebone->flag, sel_op_result, BONE_TIPSEL);
+ }
}
+ is_point_done |= is_inside;
}
/* if one of points selected, we skip the bone itself */
- if ((is_point_done == false) && (points_proj_tot == 2) &&
- BLI_lasso_is_edge_inside(data->mcords, data->moves, x0, y0, x1, y1, INT_MAX))
- {
- if (data->select) ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- else ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ if ((is_point_done == false) && (points_proj_tot == 2)) {
+ const bool is_select = ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ const bool is_inside = BLI_lasso_is_edge_inside(
+ data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX);
+ const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
+ SET_FLAG_FROM_TEST(ebone->flag, sel_op_result, (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL));
+ }
+ }
data->is_changed = true;
}
@@ -670,19 +800,20 @@ static void do_lasso_select_armature__doSelectBone(
}
}
-static void do_lasso_select_armature(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
+static void do_lasso_select_armature(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op)
{
LassoSelectUserData data;
rcti rect;
BLI_lasso_boundbox(&rect, mcords, moves);
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- if (extend == false && select)
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
ED_armature_edit_deselect_all_visible(vc->obedit);
+ }
armature_foreachScreenBone(vc, do_lasso_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
@@ -697,48 +828,52 @@ static void do_lasso_select_armature(ViewContext *vc, const int mcords[][2], sho
static void do_lasso_select_mball__doSelectElem(void *userData, struct MetaElem *ml, const float screen_co[2])
{
LassoSelectUserData *data = userData;
-
- if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], INT_MAX))
- {
- if (data->select) ml->flag |= SELECT;
- else ml->flag &= ~SELECT;
+ const bool is_select = ml->flag & SELECT;
+ const bool is_inside = (
+ BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
+ BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], INT_MAX));
+ 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(ml->flag, sel_op_result, SELECT);
data->is_changed = true;
}
}
-static void do_lasso_select_meta(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
+static void 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 (extend == false && select)
+ 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, select);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
mball_foreachScreenElem(vc, do_lasso_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
-static void do_lasso_select_meshobject__doSelectVert(
- void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
+static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
{
LassoSelectUserData *data = userData;
-
- if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED))
- {
- SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT);
+ const bool is_select = mv->flag & SELECT;
+ const bool is_inside = (
+ BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
+ BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED));
+ 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 void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
+static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op)
{
- const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0;
+ const bool use_zbuf = V3D_IS_ZBUF(vc->v3d);
Object *ob = vc->obact;
Mesh *me = ob->data;
rcti rect;
@@ -746,8 +881,9 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh
if (me == NULL || me->totvert == 0)
return;
- if (extend == false && select)
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
paintvert_deselect_all_visible(ob, SEL_DESELECT, false); /* flush selection at the end */
+ }
BLI_lasso_boundbox(&rect, mcords, moves);
@@ -756,14 +892,14 @@ 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, select);
+ edbm_backbuf_check_and_select_verts_obmode(me, sel_op);
EDBM_backbuf_free();
}
else {
LassoSelectUserData data;
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
@@ -771,12 +907,12 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh
}
- if (select == false) {
+ if (SEL_OP_CAN_DESELECT(sel_op)) {
BKE_mesh_mselect_validate(me);
}
paintvert_flush_flags(ob);
}
-static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
+static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op)
{
Object *ob = vc->obact;
Mesh *me = ob->data;
@@ -785,15 +921,16 @@ static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], sh
if (me == NULL || me->totpoly == 0)
return;
- if (extend == false && select)
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
paintface_deselect_all_visible(ob, SEL_DESELECT, false); /* flush selection at the end */
+ }
bm_vertoffs = me->totpoly + 1; /* max index array */
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, select);
+ edbm_backbuf_check_and_select_tfaces(me, sel_op);
EDBM_backbuf_free();
@@ -801,7 +938,7 @@ static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], sh
}
#if 0
-static void do_lasso_select_node(int mcords[][2], short moves, const bool select)
+static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp sel_op)
{
SpaceNode *snode = sa->spacedata.first;
@@ -818,13 +955,13 @@ static void do_lasso_select_node(int mcords[][2], short moves, const bool select
node_centf[1] = BLI_RCT_CENTER_Y(&node->totr);
ipoco_to_areaco_noclip(G.v2d, node_centf, node_cent);
- if (BLI_rcti_isect_pt_v(&rect, node_cent) && BLI_lasso_is_point_inside(mcords, moves, node_cent[0], node_cent[1])) {
- if (select) {
- node->flag |= SELECT;
- }
- else {
- node->flag &= ~SELECT;
- }
+ const bool is_select = node->flag & SELECT;
+ const bool is_inside = (
+ BLI_rcti_isect_pt_v(&rect, node_cent) &&
+ BLI_lasso_is_point_inside(mcords, moves, node_cent[0], node_cent[1]));
+ 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);
}
}
BIF_undo_push("Lasso select nodes");
@@ -834,49 +971,61 @@ static void do_lasso_select_node(int mcords[][2], short moves, const bool select
static void view3d_lasso_select(
bContext *C, ViewContext *vc,
const int mcords[][2], short moves,
- bool extend, bool select)
+ const eSelectOp sel_op)
{
Object *ob = CTX_data_active_object(C);
if (vc->obedit == NULL) { /* Object Mode */
- if (BKE_paint_select_face_test(ob))
- do_lasso_select_paintface(vc, mcords, moves, extend, select);
- else if (BKE_paint_select_vert_test(ob))
- do_lasso_select_paintvert(vc, mcords, moves, extend, select);
+ if (BKE_paint_select_face_test(ob)) {
+ 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);
+ }
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, extend, select);
+ else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
+ 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);
+ }
else {
- do_lasso_select_objects(vc, mcords, moves, extend, select);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
+ do_lasso_select_objects(vc, mcords, moves, sel_op);
}
}
else { /* Edit Mode */
- switch (vc->obedit->type) {
- case OB_MESH:
- do_lasso_select_mesh(vc, mcords, moves, extend, select);
- break;
- case OB_CURVE:
- case OB_SURF:
- do_lasso_select_curve(vc, mcords, moves, extend, select);
- break;
- case OB_LATTICE:
- do_lasso_select_lattice(vc, mcords, moves, extend, select);
- break;
- case OB_ARMATURE:
- do_lasso_select_armature(vc, mcords, moves, extend, select);
- break;
- case OB_MBALL:
- do_lasso_select_meta(vc, mcords, moves, extend, select);
- break;
- default:
- assert(!"lasso select on incorrect object type");
- break;
- }
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc->obedit->data);
+ FOREACH_OBJECT_IN_MODE_BEGIN (vc->view_layer, ob->mode, ob_iter) {
+ ED_view3d_viewcontext_init_object(vc, ob_iter);
+
+ switch (vc->obedit->type) {
+ case OB_MESH:
+ 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);
+ break;
+ case OB_LATTICE:
+ do_lasso_select_lattice(vc, mcords, moves, sel_op);
+ break;
+ case OB_ARMATURE:
+ do_lasso_select_armature(vc, mcords, moves, sel_op);
+ break;
+ case OB_MBALL:
+ 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, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc->obedit->data);
+ }
+ FOREACH_OBJECT_IN_MODE_END;
}
}
@@ -890,15 +1039,13 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op)
const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
if (mcords) {
- bool extend, select;
view3d_operator_needs_opengl(C);
/* setup view context for argument to callbacks */
ED_view3d_viewcontext_init(C, &vc);
- extend = RNA_boolean_get(op->ptr, "extend");
- select = !RNA_boolean_get(op->ptr, "deselect");
- view3d_lasso_select(C, &vc, mcords, mcords_tot, extend, select);
+ eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
+ view3d_lasso_select(C, &vc, mcords, mcords_tot, sel_op);
MEM_freeN((void *)mcords);
@@ -923,7 +1070,8 @@ void VIEW3D_OT_select_lasso(wmOperatorType *ot)
ot->flag = OPTYPE_UNDO;
/* properties */
- WM_operator_properties_gesture_lasso_select(ot);
+ WM_operator_properties_gesture_lasso(ot);
+ WM_operator_properties_select_operation(ot);
}
/* ************************** mouse select ************************* */
@@ -974,8 +1122,8 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
if (!toggle) {
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
- if (base->flag & SELECT) {
- ED_base_object_select(base, BA_DESELECT);
+ if ((base->flag & BASE_SELECTED) != 0) {
+ ED_object_base_select(base, BA_DESELECT);
changed = true;
}
}
@@ -986,8 +1134,8 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
{
/* this is a bit dodjy, there should only be ONE object with this name, but library objects can mess this up */
if (STREQ(name, base->object->id.name + 2)) {
- ED_base_object_activate(C, base);
- ED_base_object_select(base, BA_SELECT);
+ ED_object_base_activate(C, base);
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -998,7 +1146,9 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
/* undo? */
if (changed) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
}
else {
@@ -1031,14 +1181,12 @@ void VIEW3D_OT_select_menu(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle selection instead of deselecting everything first");
}
-static void deselectall_except(Scene *scene, Base *b) /* deselect all except b */
+static void deselectall_except(ViewLayer *view_layer, Base *b) /* deselect all except b */
{
- Base *base;
-
- for (base = FIRSTBASE; base; base = base->next) {
- if (base->flag & SELECT) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->flag & BASE_SELECTED) {
if (b != base) {
- ED_base_object_select(base, BA_DESELECT);
+ ED_object_base_select(base, BA_DESELECT);
}
}
}
@@ -1051,7 +1199,10 @@ static Base *object_mouse_select_menu(
short baseCount = 0;
bool ok;
LinkNode *linklist = NULL;
+ const int object_type_exclude_select = (
+ vc->v3d->object_type_exclude_viewport | vc->v3d->object_type_exclude_select);
+ /* handle base->object->select_color */
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
ok = false;
@@ -1060,13 +1211,16 @@ static Base *object_mouse_select_menu(
if (buffer) {
for (int a = 0; a < hits; a++) {
/* index was converted */
- if (base->selcol == (buffer[(4 * a) + 3] & ~0xFFFF0000)) {
+ if (base->object->select_color == (buffer[(4 * a) + 3] & ~0xFFFF0000)) {
ok = true;
break;
}
}
}
else {
+ if (object_type_exclude_select & (1 << base->object->type)) {
+ continue;
+ }
const int dist = 15 * U.pixelsize;
if (ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK) {
const int delta_px[2] = {base->sx - mval[0], base->sy - mval[1]};
@@ -1160,7 +1314,7 @@ static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits15, const
/* so check three selection levels and compare */
static int mixed_bones_object_selectbuffer(
ViewContext *vc, unsigned int *buffer, const int mval[2],
- bool use_cycle, bool enumerate,
+ bool use_cycle, bool enumerate, eV3DSelectObjectFilter select_filter,
bool *r_do_nearest)
{
rcti rect;
@@ -1172,7 +1326,7 @@ static int mixed_bones_object_selectbuffer(
/* define if we use solid nearest select or not */
if (use_cycle) {
- if (v3d->drawtype > OB_WIRE) {
+ if (v3d->shading.type > OB_WIRE) {
do_nearest = true;
if (len_manhattan_v2v2_int(mval, last_mval) < 3) {
do_nearest = false;
@@ -1181,7 +1335,7 @@ static int mixed_bones_object_selectbuffer(
copy_v2_v2_int(last_mval, mval);
}
else {
- if (v3d->drawtype > OB_WIRE) {
+ if (v3d->shading.type > OB_WIRE) {
do_nearest = true;
}
}
@@ -1199,7 +1353,7 @@ static int mixed_bones_object_selectbuffer(
view3d_opengl_select_cache_begin();
BLI_rcti_init_pt_radius(&rect, mval, 14);
- hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode);
+ hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter);
if (hits15 == 1) {
hits = selectbuffer_ret_hits_15(buffer, hits15);
goto finally;
@@ -1210,7 +1364,7 @@ static int mixed_bones_object_selectbuffer(
offs = 4 * hits15;
BLI_rcti_init_pt_radius(&rect, mval, 9);
- hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode);
+ hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter);
if (hits9 == 1) {
hits = selectbuffer_ret_hits_9(buffer, hits15, hits9);
goto finally;
@@ -1220,7 +1374,7 @@ static int mixed_bones_object_selectbuffer(
offs += 4 * hits9;
BLI_rcti_init_pt_radius(&rect, mval, 5);
- hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode);
+ hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter);
if (hits5 == 1) {
hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
goto finally;
@@ -1242,6 +1396,23 @@ static int mixed_bones_object_selectbuffer(
finally:
view3d_opengl_select_cache_end();
+ if (vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
+ const bool is_pose_mode = (vc->obact && vc->obact->mode & OB_MODE_POSE);
+ struct {
+ uint data[4];
+ } *buffer4 = (void *)buffer;
+ uint j = 0;
+ for (uint i = 0; i < hits; i++) {
+ if (((buffer4[i].data[3] & 0xFFFF0000) != 0) == is_pose_mode) {
+ if (i != j) {
+ buffer4[j] = buffer4[i];
+ }
+ j++;
+ }
+ }
+ hits = j;
+ }
+
return hits;
}
@@ -1250,8 +1421,7 @@ static Base *mouse_select_eval_buffer(
ViewContext *vc, const uint *buffer, int hits,
Base *startbase, bool has_bones, bool do_nearest)
{
- Scene *scene = vc->scene;
- View3D *v3d = vc->v3d;
+ ViewLayer *view_layer = vc->view_layer;
Base *base, *basact = NULL;
int a;
@@ -1271,7 +1441,9 @@ static Base *mouse_select_eval_buffer(
}
else {
/* only exclude active object when it is selected... */
- if (BASACT && (BASACT->flag & SELECT) && hits > 1) notcol = BASACT->selcol;
+ if (BASACT(view_layer) && (BASACT(view_layer)->flag & BASE_SELECTED) && hits > 1) {
+ notcol = BASACT(view_layer)->object->select_color;
+ }
for (a = 0; a < hits; a++) {
if (min > buffer[4 * a + 1] && notcol != (buffer[4 * a + 3] & 0xFFFF)) {
@@ -1281,10 +1453,10 @@ static Base *mouse_select_eval_buffer(
}
}
- base = FIRSTBASE;
+ base = FIRSTBASE(view_layer);
while (base) {
- if (BASE_SELECTABLE(v3d, base)) {
- if (base->selcol == selcol) break;
+ if (BASE_SELECTABLE(base)) {
+ if (base->object->select_color == selcol) break;
}
base = base->next;
}
@@ -1296,23 +1468,23 @@ static Base *mouse_select_eval_buffer(
while (base) {
/* skip objects with select restriction, to prevent prematurely ending this loop
* with an un-selectable choice */
- if (base->object->restrictflag & OB_RESTRICT_SELECT) {
+ if ((base->flag & BASE_SELECTABLE) == 0) {
base = base->next;
- if (base == NULL) base = FIRSTBASE;
+ if (base == NULL) base = FIRSTBASE(view_layer);
if (base == startbase) break;
}
- if (BASE_SELECTABLE(v3d, base)) {
+ if (BASE_SELECTABLE(base)) {
for (a = 0; a < hits; a++) {
if (has_bones) {
/* skip non-bone objects */
if ((buffer[4 * a + 3] & 0xFFFF0000)) {
- if (base->selcol == (buffer[(4 * a) + 3] & 0xFFFF))
+ if (base->object->select_color == (buffer[(4 * a) + 3] & 0xFFFF))
basact = base;
}
}
else {
- if (base->selcol == (buffer[(4 * a) + 3] & 0xFFFF))
+ if (base->object->select_color == (buffer[(4 * a) + 3] & 0xFFFF))
basact = base;
}
}
@@ -1321,7 +1493,7 @@ static Base *mouse_select_eval_buffer(
if (basact) break;
base = base->next;
- if (base == NULL) base = FIRSTBASE;
+ if (base == NULL) base = FIRSTBASE(view_layer);
if (base == startbase) break;
}
}
@@ -1340,13 +1512,17 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
/* setup view context for argument to callbacks */
view3d_operator_needs_opengl(C);
+
ED_view3d_viewcontext_init(C, &vc);
- hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, false, false, &do_nearest);
+ hits = mixed_bones_object_selectbuffer(
+ &vc, buffer, mval,
+ false, false, VIEW3D_SELECT_FILTER_NOP,
+ &do_nearest);
if (hits > 0) {
const bool has_bones = selectbuffer_has_bones(buffer, hits);
- basact = mouse_select_eval_buffer(&vc, buffer, hits, vc.scene->base.first, has_bones, do_nearest);
+ basact = mouse_select_eval_buffer(&vc, buffer, hits, vc.view_layer->object_bases.first, has_bones, do_nearest);
}
return basact;
@@ -1378,16 +1554,16 @@ static bool ed_object_select_pick(
{
ViewContext vc;
ARegion *ar = CTX_wm_region(C);
- View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
- Base *base, *startbase = NULL, *basact = NULL, *oldbasact = NULL;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base, *startbase = NULL, *basact = NULL, *oldbasact = BASACT(view_layer);
+ const eObjectMode object_mode = oldbasact ? oldbasact->object->mode : OB_MODE_OBJECT;
bool is_obedit;
float dist = ED_view3d_select_dist_px() * 1.3333f;
bool retval = false;
int hits;
const float mval_fl[2] = {(float)mval[0], (float)mval[1]};
-
/* setup view context for argument to callbacks */
ED_view3d_viewcontext_init(C, &vc);
@@ -1397,9 +1573,12 @@ static bool ed_object_select_pick(
vc.obedit = NULL;
}
+ /* In pose mode we don't want to mess with object selection. */
+ const bool is_pose_mode = (vc.obact && vc.obact->mode & OB_MODE_POSE);
+
/* always start list from basact in wire mode */
- startbase = FIRSTBASE;
- if (BASACT && BASACT->next) startbase = BASACT->next;
+ startbase = FIRSTBASE(view_layer);
+ if (BASACT(view_layer) && BASACT(view_layer)->next) startbase = BASACT(view_layer)->next;
/* This block uses the control key to make the object selected by its center point rather than its contents */
/* in editmode do not activate */
@@ -1410,16 +1589,20 @@ static bool ed_object_select_pick(
basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, toggle);
}
else {
+ const int object_type_exclude_select = (
+ vc.v3d->object_type_exclude_viewport | vc.v3d->object_type_exclude_select);
base = startbase;
while (base) {
- if (BASE_SELECTABLE(v3d, base)) {
+ if (BASE_SELECTABLE(base) &&
+ ((object_type_exclude_select & (1 << base->object->type)) == 0))
+ {
float screen_co[2];
if (ED_view3d_project_float_global(
ar, base->object->obmat[3], screen_co,
V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
{
float dist_temp = len_manhattan_v2v2(mval_fl, screen_co);
- if (base == BASACT) dist_temp += 10.0f;
+ if (base == BASACT(view_layer)) dist_temp += 10.0f;
if (dist_temp < dist) {
dist = dist_temp;
basact = base;
@@ -1428,10 +1611,23 @@ static bool ed_object_select_pick(
}
base = base->next;
- if (base == NULL) base = FIRSTBASE;
+ if (base == NULL) base = FIRSTBASE(view_layer);
if (base == startbase) break;
}
}
+ if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
+ if (is_obedit == false) {
+ if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) {
+ if (object_mode == OB_MODE_OBJECT) {
+ struct Main *bmain = CTX_data_main(C);
+ ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object);
+ }
+ if (!BKE_object_is_mode_compat(basact->object, object_mode)) {
+ basact = NULL;
+ }
+ }
+ }
+ }
}
else {
unsigned int buffer[MAXPICKBUF];
@@ -1440,7 +1636,13 @@ static bool ed_object_select_pick(
// TIMEIT_START(select_time);
/* if objects have posemode set, the bones are in the same selection buffer */
- hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, true, enumerate, &do_nearest);
+ const eV3DSelectObjectFilter select_filter = (
+ (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ?
+ VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK : VIEW3D_SELECT_FILTER_NOP);
+ hits = mixed_bones_object_selectbuffer(
+ &vc, buffer, mval,
+ true, enumerate, select_filter,
+ &do_nearest);
// TIMEIT_END(select_time);
@@ -1456,9 +1658,23 @@ static bool ed_object_select_pick(
basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, has_bones, do_nearest);
}
+ if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
+ if (is_obedit == false) {
+ if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) {
+ if (object_mode == OB_MODE_OBJECT) {
+ struct Main *bmain = CTX_data_main(C);
+ ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object);
+ }
+ if (!BKE_object_is_mode_compat(basact->object, object_mode)) {
+ basact = NULL;
+ }
+ }
+ }
+ }
+
if (has_bones && basact) {
if (basact->object->type == OB_CAMERA) {
- if (BASACT == basact) {
+ if (BASACT(view_layer) == basact) {
int i, hitresult;
bool changed = false;
@@ -1467,7 +1683,7 @@ static bool ed_object_select_pick(
/* if there's bundles in buffer select bundles first,
* so non-camera elements should be ignored in buffer */
- if (basact->selcol != (hitresult & 0xFFFF)) {
+ if (basact->object->select_color != (hitresult & 0xFFFF)) {
continue;
}
@@ -1496,11 +1712,13 @@ static bool ed_object_select_pick(
changed = true;
}
- basact->flag |= SELECT;
- basact->object->flag = basact->flag;
+ basact->flag |= BASE_SELECTED;
+ BKE_scene_object_base_flag_sync_from_base(basact);
retval = true;
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ DEG_id_tag_update(&clip->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, track);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -1516,73 +1734,110 @@ static bool ed_object_select_pick(
}
}
else if (ED_armature_pose_select_pick_with_buffer(
- scene, basact, buffer, hits, extend, deselect, toggle, do_nearest))
+ view_layer, basact, buffer, hits, extend, deselect, toggle, do_nearest))
{
/* then bone is found */
/* we make the armature selected:
* not-selected active object in posemode won't work well for tools */
- basact->flag |= SELECT;
- basact->object->flag = basact->flag;
+ basact->flag |= BASE_SELECTED;
+ BKE_scene_object_base_flag_sync_from_base(basact);
retval = true;
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, basact->object);
/* in weightpaint, we use selected bone to select vertexgroup, so no switch to new active object */
- if (BASACT && (BASACT->object->mode & OB_MODE_WEIGHT_PAINT)) {
+ if (BASACT(view_layer) && (BASACT(view_layer)->object->mode & OB_MODE_WEIGHT_PAINT)) {
/* prevent activating */
basact = NULL;
}
}
/* prevent bone selecting to pass on to object selecting */
- if (basact == BASACT)
+ if (basact == BASACT(view_layer))
basact = NULL;
}
}
}
+ if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
+ /* Disallow switching modes,
+ * special exception for edit-mode - vertex-parent operator. */
+ if (is_obedit == false) {
+ if (oldbasact && basact) {
+ if ((oldbasact->object->mode != basact->object->mode) &&
+ (oldbasact->object->mode & basact->object->mode) == 0)
+ {
+ basact = NULL;
+ }
+ }
+ }
+ }
+
/* so, do we have something selected? */
if (basact) {
retval = true;
if (vc.obedit) {
/* only do select */
- deselectall_except(scene, basact);
- ED_base_object_select(basact, BA_SELECT);
+ deselectall_except(view_layer, basact);
+ ED_object_base_select(basact, BA_SELECT);
}
/* also prevent making it active on mouse selection */
- else if (BASE_SELECTABLE(v3d, basact)) {
-
- oldbasact = BASACT;
-
+ else if (BASE_SELECTABLE(basact)) {
if (extend) {
- ED_base_object_select(basact, BA_SELECT);
+ ED_object_base_select(basact, BA_SELECT);
}
else if (deselect) {
- ED_base_object_select(basact, BA_DESELECT);
+ ED_object_base_select(basact, BA_DESELECT);
}
else if (toggle) {
- if (basact->flag & SELECT) {
+ if (basact->flag & BASE_SELECTED) {
if (basact == oldbasact) {
- ED_base_object_select(basact, BA_DESELECT);
+ ED_object_base_select(basact, BA_DESELECT);
}
}
else {
- ED_base_object_select(basact, BA_SELECT);
+ ED_object_base_select(basact, BA_SELECT);
}
}
else {
- deselectall_except(scene, basact);
- ED_base_object_select(basact, BA_SELECT);
+ /* When enabled, this puts other objects out of multi pose-mode. */
+ if (is_pose_mode == false) {
+ deselectall_except(view_layer, basact);
+ ED_object_base_select(basact, BA_SELECT);
+ }
}
if ((oldbasact != basact) && (is_obedit == false)) {
- ED_base_object_activate(C, basact); /* adds notifier */
+ ED_object_base_activate(C, basact); /* adds notifier */
+ }
+
+ /* Set special modes for grease pencil
+ The grease pencil modes are not real modes, but a hack to make the interface
+ consistent, so need some tricks to keep UI synchronized */
+ // XXX: This stuff needs reviewing (Aligorith)
+ if (false &&
+ (((oldbasact) && oldbasact->object->type == OB_GPENCIL) ||
+ (basact->object->type == OB_GPENCIL)))
+ {
+ /* set cursor */
+ if (ELEM(basact->object->mode,
+ OB_MODE_GPENCIL_PAINT,
+ OB_MODE_GPENCIL_SCULPT,
+ OB_MODE_GPENCIL_WEIGHT))
+ {
+ ED_gpencil_toggle_brush_cursor(C, true, NULL);
+ }
+ else {
+ /* TODO: maybe is better use restore */
+ ED_gpencil_toggle_brush_cursor(C, false, NULL);
+ }
}
}
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
@@ -1596,17 +1851,16 @@ typedef struct BoxSelectUserData {
const rcti *rect;
const rctf *rect_fl;
rctf _rect_fl;
- bool select;
+ eSelectOp sel_op;
/* runtime */
- int pass;
bool is_done;
bool is_changed;
} BoxSelectUserData;
static void view3d_userdata_boxselect_init(
BoxSelectUserData *r_data,
- ViewContext *vc, const rcti *rect, const bool select)
+ ViewContext *vc, const rcti *rect, const eSelectOp sel_op)
{
r_data->vc = vc;
@@ -1614,10 +1868,9 @@ static void view3d_userdata_boxselect_init(
r_data->rect_fl = &r_data->_rect_fl;
BLI_rctf_rcti_copy(&r_data->_rect_fl, rect);
- r_data->select = select;
+ r_data->sel_op = sel_op;
/* runtime */
- r_data->pass = 0;
r_data->is_done = false;
r_data->is_changed = false;
}
@@ -1631,14 +1884,17 @@ bool edge_inside_circle(const float cent[2], float radius, const float screen_co
static void do_paintvert_box_select__doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
{
BoxSelectUserData *data = userData;
-
- if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co)) {
- SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT);
+ const bool is_select = mv->flag & SELECT;
+ const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co);
+ 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);
}
}
-static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
+static int do_paintvert_box_select(
+ ViewContext *vc, rcti *rect, const eSelectOp sel_op)
{
- const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0;
+ const bool use_zbuf = V3D_IS_ZBUF(vc->v3d);
Mesh *me;
MVert *mvert;
struct ImBuf *ibuf;
@@ -1655,8 +1911,9 @@ static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, boo
return OPERATOR_CANCELLED;
}
- if (extend == false && select)
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
paintvert_deselect_all_visible(vc->obact, SEL_DESELECT, false);
+ }
if (use_zbuf) {
selar = MEM_callocN(me->totvert + 1, "selar");
@@ -1686,10 +1943,12 @@ static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, boo
mvert = me->mvert;
for (a = 1; a <= me->totvert; a++, mvert++) {
- if (selar[a]) {
- if ((mvert->flag & ME_HIDE) == 0) {
- if (select) mvert->flag |= SELECT;
- else mvert->flag &= ~SELECT;
+ if ((mvert->flag & ME_HIDE) == 0) {
+ const bool is_select = mvert->flag & SELECT;
+ const bool is_inside = (selar[a] != 0);
+ 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);
}
}
}
@@ -1704,14 +1963,14 @@ static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, boo
else {
BoxSelectUserData data;
- view3d_userdata_boxselect_init(&data, vc, rect, select);
+ view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
meshobject_foreachScreenVert(vc, do_paintvert_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
- if (select == false) {
+ if (SEL_OP_CAN_DESELECT(sel_op)) {
BKE_mesh_mselect_validate(me);
}
paintvert_flush_flags(vc->obact);
@@ -1723,39 +1982,42 @@ static void do_nurbs_box_select__doSelect(
void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
{
BoxSelectUserData *data = userData;
- Object *obedit = data->vc->obedit;
- Curve *cu = (Curve *)obedit->data;
- if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co)) {
- if (bp) {
- bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
+ const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co);
+ if (bp) {
+ const bool is_select = bp->f1 & SELECT;
+ 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);
}
- else {
- if (cu->drawflag & CU_HIDE_HANDLES) {
- /* can only be (beztindex == 0) here since handles are hidden */
- bezt->f1 = bezt->f2 = bezt->f3 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
+ }
+ else {
+ if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
+ /* can only be (beztindex == 0) here since handles are hidden */
+ const bool is_select = bezt->f2 & SELECT;
+ 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);
}
- else {
- if (beztindex == 0) {
- bezt->f1 = data->select ? (bezt->f1 | SELECT) : (bezt->f1 & ~SELECT);
- }
- else if (beztindex == 1) {
- bezt->f2 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
- }
- else {
- bezt->f3 = data->select ? (bezt->f3 | SELECT) : (bezt->f3 & ~SELECT);
- }
+ bezt->f1 = bezt->f3 = bezt->f2;
+ }
+ else {
+ char *flag_p = (&bezt->f1) + beztindex;
+ const bool is_select = *flag_p & SELECT;
+ 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);
}
}
}
}
-static int do_nurbs_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
+static int do_nurbs_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_op)
{
BoxSelectUserData data;
- view3d_userdata_boxselect_init(&data, vc, rect, select);
+ view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
- if (extend == false && select) {
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
Curve *curve = (Curve *) vc->obedit->data;
ED_curve_deselect_all(curve->editnurb);
}
@@ -1770,19 +2032,22 @@ static int do_nurbs_box_select(ViewContext *vc, rcti *rect, bool select, bool ex
static void do_lattice_box_select__doSelect(void *userData, BPoint *bp, const float screen_co[2])
{
BoxSelectUserData *data = userData;
-
- if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co)) {
- bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
+ const bool is_select = bp->f1 & SELECT;
+ const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co);
+ 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);
}
}
-static int do_lattice_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
+static int do_lattice_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_op)
{
BoxSelectUserData data;
- view3d_userdata_boxselect_init(&data, vc, rect, select);
+ view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
- if (extend == false && select)
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
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);
@@ -1793,58 +2058,72 @@ static int do_lattice_box_select(ViewContext *vc, rcti *rect, bool select, bool
static void do_mesh_box_select__doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index))
{
BoxSelectUserData *data = userData;
-
- if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co)) {
- BM_vert_select_set(data->vc->em->bm, eve, data->select);
+ const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT);
+ const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co);
+ 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);
}
}
-static void do_mesh_box_select__doSelectEdge(
+static void do_mesh_box_select__doSelectEdge_pass0(
void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
{
BoxSelectUserData *data = userData;
-
- if (EDBM_backbuf_check(bm_solidoffs + index)) {
- if (data->pass == 0) {
- if (edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b)) {
- BM_edge_select_set(data->vc->em->bm, eed, data->select);
- data->is_done = true;
- }
- }
- else {
- if (edge_inside_rect(data->rect_fl, screen_co_a, screen_co_b)) {
- BM_edge_select_set(data->vc->em->bm, eed, data->select);
- }
- }
+ const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
+ const bool is_inside = (
+ EDBM_backbuf_check(bm_solidoffs + index) &&
+ edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b));
+ 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_done = true;
+}
+static void do_mesh_box_select__doSelectEdge_pass1(
+ void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
+{
+ BoxSelectUserData *data = userData;
+ const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
+ const bool is_inside = (
+ EDBM_backbuf_check(bm_solidoffs + index) &&
+ edge_inside_rect(data->rect_fl, screen_co_a, screen_co_b));
+ 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);
}
}
static void do_mesh_box_select__doSelectFace(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
{
BoxSelectUserData *data = userData;
-
- if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co)) {
- BM_face_select_set(data->vc->em->bm, efa, data->select);
+ const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT);
+ const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co);
+ 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);
}
}
-static int do_mesh_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
+static int do_mesh_box_select(
+ ViewContext *vc, rcti *rect, const eSelectOp sel_op)
{
BoxSelectUserData data;
ToolSettings *ts = vc->scene->toolsettings;
int bbsel;
- view3d_userdata_boxselect_init(&data, vc, rect, select);
+ view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
- if (extend == false && select)
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT);
+ }
/* for non zbuf projections, don't change the GL state */
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- glLoadMatrixf(vc->rv3d->viewmat);
+ GPU_matrix_set(vc->rv3d->viewmat);
bbsel = EDBM_backbuf_border_init(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
if (ts->selectmode & SCE_SELECT_VERTEX) {
if (bbsel) {
- edbm_backbuf_check_and_select_verts(vc->em, select);
+ 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);
@@ -1852,19 +2131,15 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, bool select, bool ext
}
if (ts->selectmode & SCE_SELECT_EDGE) {
/* Does both bbsel and non-bbsel versions (need screen cos for both) */
-
- data.pass = 0;
- mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
-
- if (data.is_done == 0) {
- data.pass = 1;
- mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge_pass0, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ if (data.is_done == false) {
+ mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge_pass1, &data, V3D_PROJ_TEST_CLIP_NEAR);
}
}
if (ts->selectmode & SCE_SELECT_FACE) {
if (bbsel) {
- edbm_backbuf_check_and_select_faces(vc->em, select);
+ 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);
@@ -1878,7 +2153,9 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, bool select, bool ext
return OPERATOR_FINISHED;
}
-static int do_meta_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
+static int do_meta_box_select(
+ ViewContext *vc,
+ const rcti *rect, const eSelectOp sel_op)
{
MetaBall *mb = (MetaBall *)vc->obedit->data;
MetaElem *ml;
@@ -1887,47 +2164,74 @@ static int do_meta_box_select(ViewContext *vc, rcti *rect, bool select, bool ext
unsigned int buffer[MAXPICKBUF];
int hits;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL);
+ hits = view3d_opengl_select(
+ vc, buffer, MAXPICKBUF, rect,
+ VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
- if (extend == false && select)
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
BKE_mball_deselect_all(mb);
+ }
for (ml = mb->editelems->first; ml; ml = ml->next) {
+ bool is_inside_1 = false;
+ bool is_inside_2 = false;
for (a = 0; a < hits; a++) {
if (ml->selcol1 == buffer[(4 * a) + 3]) {
- ml->flag |= MB_SCALE_RAD;
- if (select) ml->flag |= SELECT;
- else ml->flag &= ~SELECT;
+ is_inside_1 = true;
break;
}
if (ml->selcol2 == buffer[(4 * a) + 3]) {
- ml->flag &= ~MB_SCALE_RAD;
- if (select) ml->flag |= SELECT;
- else ml->flag &= ~SELECT;
+ is_inside_2 = true;
break;
}
}
+ if (is_inside_1) {
+ ml->flag |= MB_SCALE_RAD;
+ }
+ if (is_inside_2) {
+ ml->flag &= ~MB_SCALE_RAD;
+ }
+ const bool is_select = (ml->flag & SELECT);
+ const bool is_inside = is_inside_1 || is_inside_2;
+ 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(ml->flag, sel_op_result, SELECT);
+ }
}
return OPERATOR_FINISHED;
}
-static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
+static int do_armature_box_select(
+ ViewContext *vc,
+ const rcti *rect, const eSelectOp sel_op)
{
- bArmature *arm = vc->obedit->data;
+ /* TODO(campbell): Full support for seleciton operations for edit bones. */
+ const bool select = sel_op == SEL_OP_ADD;
int a;
unsigned int buffer[MAXPICKBUF];
int hits;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL);
+ hits = view3d_opengl_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, &objects_len);
/* clear flag we use to detect point was affected */
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next)
- ebone->flag &= ~BONE_DONE;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ bArmature *arm = obedit->data;
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ ebone->flag &= ~BONE_DONE;
+ }
+ }
- if (extend == false && select)
- ED_armature_edit_deselect_all_visible(vc->obedit);
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ ED_armature_edit_deselect_all_visible_multi(objects, objects_len);
+ }
/* first we only check points inside the border */
for (a = 0; a < hits; a++) {
@@ -1936,7 +2240,9 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool
if ((index & 0xFFFF0000) == 0) {
continue;
}
- EditBone *ebone = BLI_findlink(arm->edbo, index & ~(BONESEL_ANY));
+
+ EditBone *ebone;
+ ED_armature_object_and_ebone_from_select_buffer(objects, objects_len, index, &ebone);
if ((select == false) || ((ebone->flag & BONE_UNSELECTABLE) == 0)) {
if (index & BONESEL_TIP) {
ebone->flag |= BONE_DONE;
@@ -1954,10 +2260,14 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool
}
/* now we have to flush tag from parents... */
- for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
- if (ebone->parent->flag & BONE_DONE) {
- ebone->flag |= BONE_DONE;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ bArmature *arm = obedit->data;
+ for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+ if (ebone->parent->flag & BONE_DONE) {
+ ebone->flag |= BONE_DONE;
+ }
}
}
}
@@ -1967,7 +2277,8 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool
int index = buffer[(4 * a) + 3];
if (index != -1) {
if (index & BONESEL_BONE) {
- EditBone *ebone = BLI_findlink(arm->edbo, index & ~(BONESEL_ANY));
+ EditBone *ebone;
+ ED_armature_object_and_ebone_from_select_buffer(objects, objects_len, index, &ebone);
if ((select == false) || ((ebone->flag & BONE_UNSELECTABLE) == 0)) {
if (!(ebone->flag & BONE_DONE)) {
if (select) {
@@ -1982,45 +2293,122 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool
}
}
- ED_armature_edit_sync_selection(arm->edbo);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ bArmature *arm = obedit->data;
+ ED_armature_edit_sync_selection(arm->edbo);
+ }
+
+ MEM_freeN(objects);
return hits > 0 ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
-static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, bool select, bool extend)
+/**
+ * Compare result of 'GPU_select': 'uint[4]',
+ * needed for when we need to align with object draw-order.
+ */
+static int opengl_bone_select_buffer_cmp(const void *sel_a_p, const void *sel_b_p)
+{
+ /* 4th element is select id */
+ uint sel_a = ((uint *)sel_a_p)[3];
+ uint sel_b = ((uint *)sel_b_p)[3];
+
+#ifdef __BIG_ENDIAN__
+ BLI_endian_switch_uint32(&sel_a);
+ BLI_endian_switch_uint32(&sel_b);
+#endif
+
+ if (sel_a < sel_b) {
+ return -1;
+ }
+ else if (sel_a > sel_b) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+static int do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const eSelectOp sel_op)
{
- Bone *bone;
- Object *ob = vc->obact;
- unsigned int *vbuffer = NULL; /* selection buffer */
- unsigned int *col; /* color in buffer */
- int bone_only;
- int bone_selected = 0;
int totobj = MAXPICKBUF; /* XXX solve later */
- int hits;
- if ((ob) && (ob->mode & OB_MODE_POSE))
- bone_only = 1;
- else
- bone_only = 0;
+ /* selection buffer now has bones potentially too, so we add MAXPICKBUF */
+ uint *vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(uint[4]), "selection buffer");
+ const eV3DSelectObjectFilter select_filter = (
+ (vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ?
+ VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK : VIEW3D_SELECT_FILTER_NOP);
+ const int hits = view3d_opengl_select(
+ vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect,
+ VIEW3D_SELECT_ALL, select_filter);
- if (extend == false && select) {
- if (bone_only) {
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
- {
- if ((select == false) || ((pchan->bone->flag & BONE_UNSELECTABLE) == 0)) {
- pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ for (Base *base = vc->view_layer->object_bases.first; base; base = base->next) {
+ base->object->id.tag &= ~LIB_TAG_DOIT;
+ }
+
+ Base **bases = NULL;
+ BLI_array_declare(bases);
+
+ /* The draw order doesn't always match the order we populate the engine, see: T51695. */
+ if (hits > 0) {
+ qsort(vbuffer, hits, sizeof(uint[4]), opengl_bone_select_buffer_cmp);
+
+ for (Base *base = vc->view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_SELECTABLE(base)) {
+ if ((base->object->select_color & 0x0000FFFF) != 0) {
+ BLI_array_append(bases, base);
}
}
- CTX_DATA_END;
}
- else {
- object_deselect_all_visible(vc->scene, vc->v3d);
+ }
+
+ for (const uint *col = vbuffer + 3, *col_end = col + (hits * 4); col < col_end; col += 4) {
+ Bone *bone;
+ Base *base = ED_armature_base_and_bone_from_select_buffer(bases, BLI_array_len(bases), *col, &bone);
+ base->object->id.tag |= LIB_TAG_DOIT;
+ }
+
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ object_deselect_all_visible(vc->view_layer);
+ }
+
+ for (Base *base = vc->view_layer->object_bases.first; base && hits; base = base->next) {
+ if (BASE_SELECTABLE(base)) {
+ const bool is_select = base->flag & BASE_SELECTED;
+ const bool is_inside = base->object->id.tag & LIB_TAG_DOIT;
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ ED_object_base_select(base, sel_op_result ? BA_SELECT : BA_DESELECT);
+ }
}
+ DEG_id_tag_update(&vc->scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
}
+ if (bases != NULL) {
+ MEM_freeN(bases);
+ }
+ MEM_freeN(vbuffer);
+
+ return hits > 0 ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+}
+
+static int 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);
+
+ int totobj = MAXPICKBUF; /* XXX solve later */
+
/* selection buffer now has bones potentially too, so we add MAXPICKBUF */
- vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(unsigned int), "selection buffer");
- hits = view3d_opengl_select(vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL);
+ uint *vbuffer = MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(uint[4]), "selection buffer");
+ const eV3DSelectObjectFilter select_filter = (
+ (vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ?
+ VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK : VIEW3D_SELECT_FILTER_NOP);
+ const int hits = view3d_opengl_select(
+ vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect,
+ VIEW3D_SELECT_ALL, select_filter);
/*
* LOGIC NOTES (theeth):
* The buffer and ListBase have the same relative order, which makes the selection
@@ -2028,61 +2416,57 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
* is the same as the object, we have a hit and can move to the next color
* and object pair, if not, just move to the next object,
* keeping the same color until we have a hit.
- *
- * The buffer order is defined by OGL standard, hopefully no stupid GFX card
- * does it incorrectly.
*/
- if (hits > 0) { /* no need to loop if there's no hit */
- Base *base;
- col = vbuffer + 3;
-
- for (base = vc->scene->base.first; base && hits; base = base->next) {
- if (BASE_SELECTABLE(vc->v3d, base)) {
- while (base->selcol == (*col & 0xFFFF)) { /* we got an object */
- if (*col & 0xFFFF0000) { /* we got a bone */
- bone = ED_armature_bone_find_index(base->object, *col & ~(BONESEL_ANY));
- if (bone) {
- if (select) {
- if ((bone->flag & BONE_UNSELECTABLE) == 0) {
- bone->flag |= BONE_SELECTED;
- bone_selected = 1;
- }
- }
- else {
- bArmature *arm = base->object->data;
- bone->flag &= ~BONE_SELECTED;
- if (arm->act_bone == bone)
- arm->act_bone = NULL;
- }
- }
- }
- else if (!bone_only) {
- ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT);
- }
+ if (hits > 0) {
+ /* no need to loop if there's no hit */
- col += 4; /* next color */
- hits--;
- if (hits == 0) break;
- }
- }
+ /* The draw order doesn't always match the order we populate the engine, see: T51695. */
+ qsort(vbuffer, hits, sizeof(uint[4]), opengl_bone_select_buffer_cmp);
+
+ for (const uint *col = vbuffer + 3, *col_end = col + (hits * 4); col < col_end; col += 4) {
+ Bone *bone;
+ Base *base = ED_armature_base_and_bone_from_select_buffer(bases, bases_len, *col, &bone);
- if (bone_selected) {
- if (base->object && (base->object->type == OB_ARMATURE)) {
- bArmature *arm = base->object->data;
+ if (base == NULL) {
+ continue;
+ }
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, base->object);
+ /* Loop over contiguous bone hits for 'base'. */
+ for (; col != col_end; col += 4) {
+ /* should never fail */
+ if (bone != NULL) {
+ base->object->id.tag |= LIB_TAG_DOIT;
+ bone->flag |= BONE_DONE;
+ }
- if (arm && (arm->flag & ARM_HAS_VIZ_DEPS)) {
- /* mask modifier ('armature' mode), etc. */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ /* Select the next bone if we're not switching bases. */
+ if (col + 4 != col_end) {
+ if ((base->object->select_color & 0x0000FFFF) != (col[4] & 0x0000FFFF)) {
+ break;
+ }
+ if (base->object->pose != NULL) {
+ const uint hit_bone = (col[4] & ~BONESEL_ANY) >> 16;
+ bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);
+ bone = pchan ? pchan->bone : NULL;
+ }
+ else {
+ bone = NULL;
}
}
}
}
+ }
+ const bool changed_multi = do_pose_tag_select_op_exec(bases, bases_len, sel_op);
+ if (changed_multi) {
+ DEG_id_tag_update(&vc->scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
}
+
+ if (bases != NULL) {
+ MEM_freeN(bases);
+ }
MEM_freeN(vbuffer);
return hits > 0 ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
@@ -2092,9 +2476,6 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
{
ViewContext vc;
rcti rect;
- bool extend;
- bool select;
-
int ret = OPERATOR_CANCELLED;
view3d_operator_needs_opengl(C);
@@ -2102,68 +2483,88 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
/* setup view context for argument to callbacks */
ED_view3d_viewcontext_init(C, &vc);
- select = !RNA_boolean_get(op->ptr, "deselect");
- extend = RNA_boolean_get(op->ptr, "extend");
+ eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
WM_operator_properties_border_to_rcti(op, &rect);
if (vc.obedit) {
- switch (vc.obedit->type) {
- case OB_MESH:
- vc.em = BKE_editmesh_from_object(vc.obedit);
- ret = do_mesh_box_select(&vc, &rect, select, extend);
-// if (EM_texFaceCheck())
- if (ret & OPERATOR_FINISHED) {
- 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, select, extend);
- if (ret & OPERATOR_FINISHED) {
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
- }
- break;
- case OB_MBALL:
- ret = do_meta_box_select(&vc, &rect, select, extend);
- if (ret & OPERATOR_FINISHED) {
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
- }
- break;
- case OB_ARMATURE:
- ret = do_armature_box_select(&vc, &rect, select, extend);
- if (ret & OPERATOR_FINISHED) {
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit);
- }
- break;
- case OB_LATTICE:
- ret = do_lattice_box_select(&vc, &rect, select, extend);
- if (ret & OPERATOR_FINISHED) {
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
- }
- break;
- default:
- assert(!"border select on incorrect object type");
- break;
+
+ FOREACH_OBJECT_IN_MODE_BEGIN (vc.view_layer, vc.obedit->mode, ob_iter) {
+ ED_view3d_viewcontext_init_object(&vc, ob_iter);
+
+ 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) {
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
+ 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) {
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
+ 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) {
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
+ 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) {
+ DEG_id_tag_update(&vc.obedit->id, DEG_TAG_SELECT_UPDATE);
+ 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) {
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
+ }
+ break;
+ default:
+ assert(!"border select on incorrect object type");
+ break;
+ }
}
+ FOREACH_OBJECT_IN_MODE_END;
}
else { /* no editmode, unified for bones and objects */
if (vc.obact && vc.obact->mode & OB_MODE_SCULPT) {
- ret = ED_sculpt_mask_box_select(C, &vc, &rect, select, extend);
+ /* 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);
}
else if (vc.obact && BKE_paint_select_face_test(vc.obact)) {
- ret = do_paintface_box_select(&vc, &rect, select, extend);
+ ret |= 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, select, extend);
+ ret |= do_paintvert_box_select(&vc, &rect, sel_op);
}
else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) {
- ret = PE_border_select(C, &rect, select, extend);
+ ret |= PE_border_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);
}
else { /* object mode with none active */
- ret = do_object_pose_box_select(C, &vc, &rect, select, extend);
+ ret |= do_object_box_select(C, &vc, &rect, sel_op);
}
}
+ if (ret & OPERATOR_FINISHED) {
+ ret = OPERATOR_FINISHED;
+ }
+ else {
+ ret = OPERATOR_CANCELLED;
+ }
+
return ret;
}
@@ -2189,7 +2590,8 @@ void VIEW3D_OT_select_border(wmOperatorType *ot)
ot->flag = OPTYPE_UNDO;
/* rna */
- WM_operator_properties_gesture_border_select(ot);
+ WM_operator_properties_gesture_border(ot);
+ WM_operator_properties_select_operation(ot);
}
@@ -2200,7 +2602,7 @@ static bool ed_wpaint_vertex_select_pick(
bool extend, bool deselect, bool toggle, Object *obact)
{
View3D *v3d = CTX_wm_view3d(C);
- const bool use_zbuf = (v3d->flag & V3D_ZBUF_SELECT) != 0;
+ const bool use_zbuf = V3D_IS_ZBUF(v3d);
Mesh *me = obact->data; /* already checked for NULL */
unsigned int index = 0;
@@ -2231,6 +2633,7 @@ static bool ed_wpaint_vertex_select_pick(
}
paintvert_flush_flags(obact);
+ DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
return true;
}
@@ -2319,8 +2722,8 @@ void VIEW3D_OT_select(wmOperatorType *ot)
PropertyRNA *prop;
/* identifiers */
- ot->name = "Activate/Select";
- ot->description = "Activate/select item(s)";
+ ot->name = "Select";
+ ot->description = "Select and activate item(s)";
ot->idname = "VIEW3D_OT_select";
/* api callbacks */
@@ -2415,7 +2818,7 @@ static void mesh_circle_select(ViewContext *vc, const bool select, const int mva
if (ts->selectmode & SCE_SELECT_VERTEX) {
if (bbsel) {
- edbm_backbuf_check_and_select_verts(vc->em, select);
+ edbm_backbuf_check_and_select_verts(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
}
else {
mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
@@ -2424,7 +2827,7 @@ static void mesh_circle_select(ViewContext *vc, const bool select, const int mva
if (ts->selectmode & SCE_SELECT_EDGE) {
if (bbsel) {
- edbm_backbuf_check_and_select_edges(vc->em, select);
+ edbm_backbuf_check_and_select_edges(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
}
else {
mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
@@ -2433,7 +2836,7 @@ static void mesh_circle_select(ViewContext *vc, const bool select, const int mva
if (ts->selectmode & SCE_SELECT_FACE) {
if (bbsel) {
- edbm_backbuf_check_and_select_faces(vc->em, select);
+ edbm_backbuf_check_and_select_faces(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
}
else {
mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
@@ -2454,14 +2857,13 @@ static void paint_facesel_circle_select(ViewContext *vc, const bool select, cons
bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
if (bbsel) {
- edbm_backbuf_check_and_select_tfaces(me, select);
+ edbm_backbuf_check_and_select_tfaces(me, select ? SEL_OP_ADD : SEL_OP_SUB);
EDBM_backbuf_free();
paintface_flush_flags(ob, SELECT);
}
}
-static void paint_vertsel_circle_select_doSelectVert(
- void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
+static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
{
CircleSelectUserData *data = userData;
@@ -2471,7 +2873,7 @@ static void paint_vertsel_circle_select_doSelectVert(
}
static void paint_vertsel_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
{
- const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0;
+ const bool use_zbuf = V3D_IS_ZBUF(vc->v3d);
Object *ob = vc->obact;
Mesh *me = ob->data;
bool bbsel;
@@ -2482,7 +2884,7 @@ static void paint_vertsel_circle_select(ViewContext *vc, const bool select, cons
bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
if (bbsel) {
- edbm_backbuf_check_and_select_verts_obmode(me, select);
+ edbm_backbuf_check_and_select_verts_obmode(me, select ? SEL_OP_ADD : SEL_OP_SET);
EDBM_backbuf_free();
}
}
@@ -2506,15 +2908,13 @@ static void nurbscurve_circle_doSelect(
void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
{
CircleSelectUserData *data = userData;
- Object *obedit = data->vc->obedit;
- Curve *cu = (Curve *)obedit->data;
if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
if (bp) {
bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
}
else {
- if (cu->drawflag & CU_HIDE_HANDLES) {
+ if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
/* can only be (beztindex == 0) here since handles are hidden */
bezt->f1 = bezt->f2 = bezt->f3 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
}
@@ -2632,14 +3032,7 @@ static void pose_circle_select(ViewContext *vc, const bool select, const int mva
pose_foreachScreenBone(vc, do_circle_select_pose__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
if (data.is_changed) {
- bArmature *arm = vc->obact->data;
-
- WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obact);
-
- if (arm->flag & ARM_HAS_VIZ_DEPS) {
- /* mask modifier ('armature' mode), etc. */
- DAG_id_tag_update(&vc->obact->id, OB_RECALC_DATA);
- }
+ ED_pose_bone_select_tag_update(vc->obact);
}
}
@@ -2749,7 +3142,8 @@ static void mball_circle_select(ViewContext *vc, const bool select, const int mv
/** Callbacks for circle selection in Editmode */
-static void obedit_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
+static void obedit_circle_select(
+ ViewContext *vc, const bool select, const int mval[2], float rad)
{
switch (vc->obedit->type) {
case OB_MESH:
@@ -2775,23 +3169,23 @@ static void obedit_circle_select(ViewContext *vc, const bool select, const int m
static bool object_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
{
- Scene *scene = vc->scene;
+ ViewLayer *view_layer = vc->view_layer;
const float radius_squared = rad * rad;
const float mval_fl[2] = {mval[0], mval[1]};
bool changed = false;
- const int select_flag = select ? SELECT : 0;
+ const int select_flag = select ? BASE_SELECTED : 0;
Base *base;
- for (base = FIRSTBASE; base; base = base->next) {
- if (BASE_SELECTABLE(vc->v3d, base) && ((base->flag & SELECT) != select_flag)) {
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
+ if (BASE_SELECTABLE(base) && ((base->flag & BASE_SELECTED) != select_flag)) {
float screen_co[2];
if (ED_view3d_project_float_global(
vc->ar, base->object->obmat[3], screen_co,
V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
{
if (len_squared_v2v2(mval_fl, screen_co) <= radius_squared) {
- ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT);
+ ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
changed = true;
}
}
@@ -2805,43 +3199,58 @@ static bool object_circle_select(ViewContext *vc, const bool select, const int m
static int view3d_circle_select_exec(bContext *C, wmOperator *op)
{
ViewContext vc;
- ED_view3d_viewcontext_init(C, &vc);
- Object *obact = vc.obact;
- Object *obedit = vc.obedit;
const int radius = RNA_int_get(op->ptr, "radius");
const bool select = !RNA_boolean_get(op->ptr, "deselect");
const int mval[2] = {RNA_int_get(op->ptr, "x"),
RNA_int_get(op->ptr, "y")};
+
+ ED_view3d_viewcontext_init(C, &vc);
+
+ Object *obact = vc.obact;
+ Object *obedit = vc.obedit;
+
if (obedit || BKE_paint_select_elem_test(obact) ||
(obact && (obact->mode & (OB_MODE_PARTICLE_EDIT | OB_MODE_POSE))) )
{
view3d_operator_needs_opengl(C);
- if (CTX_data_edit_object(C)) {
- obedit_circle_select(&vc, select, mval, (float)radius);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
- }
- else if (BKE_paint_select_face_test(obact)) {
- paint_facesel_circle_select(&vc, select, mval, (float)radius);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
- }
- else if (BKE_paint_select_vert_test(obact)) {
- paint_vertsel_circle_select(&vc, select, mval, (float)radius);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
- }
- else if (obact->mode & OB_MODE_POSE) {
- pose_circle_select(&vc, select, mval, (float)radius);
- }
- else {
- return PE_circle_select(C, select, mval, (float)radius);
+ FOREACH_OBJECT_IN_MODE_BEGIN (vc.view_layer, obact->mode, ob_iter) {
+ ED_view3d_viewcontext_init_object(&vc, ob_iter);
+
+ obact = vc.obact;
+ obedit = vc.obedit;
+
+ if (CTX_data_edit_object(C)) {
+ obedit_circle_select(&vc, select, mval, (float)radius);
+ DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
+ }
+ else if (BKE_paint_select_face_test(obact)) {
+ paint_facesel_circle_select(&vc, select, mval, (float)radius);
+ DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
+ }
+ else if (BKE_paint_select_vert_test(obact)) {
+ paint_vertsel_circle_select(&vc, select, mval, (float)radius);
+ DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
+ }
+ else if (obact->mode & OB_MODE_POSE) {
+ pose_circle_select(&vc, select, mval, (float)radius);
+ }
+ else {
+ return PE_circle_select(C, select, mval, (float)radius);
+ }
}
+ FOREACH_OBJECT_IN_MODE_END;
}
else if (obact && obact->mode & OB_MODE_SCULPT) {
return OPERATOR_CANCELLED;
}
else {
if (object_circle_select(&vc, select, mval, (float)radius)) {
+ DEG_id_tag_update(&vc.scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc.scene);
}
}