Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / space_view3d / view3d_select.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2008 Blender Foundation.
19  * All rights reserved.
20  *
21  *
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/editors/space_view3d/view3d_select.c
28  *  \ingroup spview3d
29  */
30
31
32 #include <string.h>
33 #include <stdio.h>
34 #include <math.h>
35 #include <float.h>
36 #include <assert.h>
37
38 #include "DNA_action_types.h"
39 #include "DNA_armature_types.h"
40 #include "DNA_curve_types.h"
41 #include "DNA_meta_types.h"
42 #include "DNA_mesh_types.h"
43 #include "DNA_meshdata_types.h"
44 #include "DNA_object_types.h"
45 #include "DNA_scene_types.h"
46 #include "DNA_tracking_types.h"
47 #include "DNA_gpencil_types.h"
48
49 #include "MEM_guardedalloc.h"
50
51 #include "BLI_array.h"
52 #include "BLI_math.h"
53 #include "BLI_lasso_2d.h"
54 #include "BLI_rect.h"
55 #include "BLI_linklist.h"
56 #include "BLI_listbase.h"
57 #include "BLI_string.h"
58 #include "BLI_utildefines.h"
59
60 #ifdef __BIG_ENDIAN__
61 #  include "BLI_endian_switch.h"
62 #endif
63
64 /* vertex box select */
65 #include "IMB_imbuf_types.h"
66 #include "IMB_imbuf.h"
67 #include "BKE_global.h"
68
69 #include "BKE_armature.h"
70 #include "BKE_context.h"
71 #include "BKE_curve.h"
72 #include "BKE_layer.h"
73 #include "BKE_mball.h"
74 #include "BKE_mesh.h"
75 #include "BKE_object.h"
76 #include "BKE_paint.h"
77 #include "BKE_editmesh.h"
78 #include "BKE_scene.h"
79 #include "BKE_tracking.h"
80 #include "BKE_workspace.h"
81
82 #include "DEG_depsgraph.h"
83
84 #include "WM_api.h"
85 #include "WM_types.h"
86
87 #include "RNA_access.h"
88 #include "RNA_define.h"
89 #include "RNA_enum_types.h"
90
91 #include "ED_armature.h"
92 #include "ED_curve.h"
93 #include "ED_lattice.h"
94 #include "ED_particle.h"
95 #include "ED_mesh.h"
96 #include "ED_object.h"
97 #include "ED_screen.h"
98 #include "ED_sculpt.h"
99 #include "ED_mball.h"
100 #include "ED_gpencil.h"
101
102 #include "UI_interface.h"
103
104 #include "GPU_draw.h"
105 #include "GPU_glew.h"
106 #include "GPU_matrix.h"
107
108 #include "view3d_intern.h"  /* own include */
109
110 // #include "PIL_time_utildefines.h"
111
112 float ED_view3d_select_dist_px(void)
113 {
114         return 75.0f * U.pixelsize;
115 }
116
117 /* TODO: should return whether there is valid context to continue */
118 void ED_view3d_viewcontext_init(bContext *C, ViewContext *vc)
119 {
120         memset(vc, 0, sizeof(ViewContext));
121         vc->ar = CTX_wm_region(C);
122         vc->bmain = CTX_data_main(C);
123         vc->depsgraph = CTX_data_depsgraph(C);
124         vc->scene = CTX_data_scene(C);
125         vc->view_layer = CTX_data_view_layer(C);
126         vc->v3d = CTX_wm_view3d(C);
127         vc->win = CTX_wm_window(C);
128         vc->rv3d = CTX_wm_region_view3d(C);
129         vc->obact = CTX_data_active_object(C);
130         vc->obedit = CTX_data_edit_object(C);
131 }
132
133 void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact)
134 {
135         vc->obact = obact;
136         if (vc->obedit) {
137                 BLI_assert(BKE_object_is_in_editmode(obact));
138                 vc->obedit = obact;
139                 /* previous selections are now invalid. */
140                 vc->v3d->flag |= V3D_INVALID_BACKBUF;
141
142                 if (vc->em) {
143                         vc->em = BKE_editmesh_from_object(vc->obedit);
144                 }
145         }
146 }
147
148 /* ********************** view3d_select: selection manipulations ********************* */
149
150 /* local prototypes */
151
152 static void edbm_backbuf_check_and_select_verts(BMEditMesh *em, const bool select)
153 {
154         BMVert *eve;
155         BMIter iter;
156         unsigned int index = bm_wireoffs;
157
158         BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
159                 if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
160                         if (EDBM_backbuf_check(index)) {
161                                 BM_vert_select_set(em->bm, eve, select);
162                         }
163                 }
164                 index++;
165         }
166 }
167
168 static void edbm_backbuf_check_and_select_edges(BMEditMesh *em, const bool select)
169 {
170         BMEdge *eed;
171         BMIter iter;
172         unsigned int index = bm_solidoffs;
173
174         BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
175                 if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
176                         if (EDBM_backbuf_check(index)) {
177                                 BM_edge_select_set(em->bm, eed, select);
178                         }
179                 }
180                 index++;
181         }
182 }
183
184 static void edbm_backbuf_check_and_select_faces(BMEditMesh *em, const bool select)
185 {
186         BMFace *efa;
187         BMIter iter;
188         unsigned int index = 1;
189
190         BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
191                 if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
192                         if (EDBM_backbuf_check(index)) {
193                                 BM_face_select_set(em->bm, efa, select);
194                         }
195                 }
196                 index++;
197         }
198 }
199
200
201 /* object mode, edbm_ prefix is confusing here, rename? */
202 static void edbm_backbuf_check_and_select_verts_obmode(Mesh *me, const bool select)
203 {
204         MVert *mv = me->mvert;
205         unsigned int index;
206
207         if (mv) {
208                 for (index = 1; index <= me->totvert; index++, mv++) {
209                         if (EDBM_backbuf_check(index)) {
210                                 if (!(mv->flag & ME_HIDE)) {
211                                         mv->flag = select ? (mv->flag | SELECT) : (mv->flag & ~SELECT);
212                                 }
213                         }
214                 }
215         }
216 }
217
218 /* object mode, edbm_ prefix is confusing here, rename? */
219 static void edbm_backbuf_check_and_select_tfaces(Mesh *me, const bool select)
220 {
221         MPoly *mpoly = me->mpoly;
222         unsigned int index;
223
224         if (mpoly) {
225                 for (index = 1; index <= me->totpoly; index++, mpoly++) {
226                         if (EDBM_backbuf_check(index)) {
227                                 mpoly->flag = select ? (mpoly->flag | ME_FACE_SEL) : (mpoly->flag & ~ME_FACE_SEL);
228                         }
229                 }
230         }
231 }
232
233 /* *********************** GESTURE AND LASSO ******************* */
234
235 typedef struct LassoSelectUserData {
236         ViewContext *vc;
237         const rcti *rect;
238         const rctf *rect_fl;
239         rctf       _rect_fl;
240         const int (*mcords)[2];
241         int moves;
242         bool select;
243
244         /* runtime */
245         int pass;
246         bool is_done;
247         bool is_changed;
248 } LassoSelectUserData;
249
250 static void view3d_userdata_lassoselect_init(
251         LassoSelectUserData *r_data,
252         ViewContext *vc, const rcti *rect, const int (*mcords)[2],
253         const int moves, const bool select)
254 {
255         r_data->vc = vc;
256
257         r_data->rect = rect;
258         r_data->rect_fl = &r_data->_rect_fl;
259         BLI_rctf_rcti_copy(&r_data->_rect_fl, rect);
260
261         r_data->mcords = mcords;
262         r_data->moves = moves;
263         r_data->select = select;
264
265         /* runtime */
266         r_data->pass = 0;
267         r_data->is_done = false;
268         r_data->is_changed = false;
269 }
270
271 static bool view3d_selectable_data(bContext *C)
272 {
273         Object *ob = CTX_data_active_object(C);
274
275         if (!ED_operator_region_view3d_active(C))
276                 return 0;
277
278         if (ob) {
279                 if (ob->mode & OB_MODE_EDIT) {
280                         if (ob->type == OB_FONT) {
281                                 return 0;
282                         }
283                 }
284                 else {
285                         if ((ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) &&
286                             !BKE_paint_select_elem_test(ob))
287                         {
288                                 return 0;
289                         }
290                 }
291         }
292
293         return 1;
294 }
295
296
297 /* helper also for borderselect */
298 static bool edge_fully_inside_rect(const rctf *rect, const float v1[2], const float v2[2])
299 {
300         return BLI_rctf_isect_pt_v(rect, v1) && BLI_rctf_isect_pt_v(rect, v2);
301 }
302
303 static bool edge_inside_rect(const rctf *rect, const float v1[2], const float v2[2])
304 {
305         int d1, d2, d3, d4;
306
307         /* check points in rect */
308         if (edge_fully_inside_rect(rect, v1, v2)) return 1;
309
310         /* check points completely out rect */
311         if (v1[0] < rect->xmin && v2[0] < rect->xmin) return 0;
312         if (v1[0] > rect->xmax && v2[0] > rect->xmax) return 0;
313         if (v1[1] < rect->ymin && v2[1] < rect->ymin) return 0;
314         if (v1[1] > rect->ymax && v2[1] > rect->ymax) return 0;
315
316         /* simple check lines intersecting. */
317         d1 = (v1[1] - v2[1]) * (v1[0] - rect->xmin) + (v2[0] - v1[0]) * (v1[1] - rect->ymin);
318         d2 = (v1[1] - v2[1]) * (v1[0] - rect->xmin) + (v2[0] - v1[0]) * (v1[1] - rect->ymax);
319         d3 = (v1[1] - v2[1]) * (v1[0] - rect->xmax) + (v2[0] - v1[0]) * (v1[1] - rect->ymax);
320         d4 = (v1[1] - v2[1]) * (v1[0] - rect->xmax) + (v2[0] - v1[0]) * (v1[1] - rect->ymin);
321
322         if (d1 < 0 && d2 < 0 && d3 < 0 && d4 < 0) return 0;
323         if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0) return 0;
324
325         return 1;
326 }
327
328 static void do_lasso_select_pose__doSelectBone(
329         void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2])
330 {
331         LassoSelectUserData *data = userData;
332         bArmature *arm = data->vc->obact->data;
333
334         if (PBONE_SELECTABLE(arm, pchan->bone)) {
335                 bool is_point_done = false;
336                 int points_proj_tot = 0;
337
338                 const int x0 = screen_co_a[0];
339                 const int y0 = screen_co_a[1];
340                 const int x1 = screen_co_b[0];
341                 const int y1 = screen_co_b[1];
342
343                 /* project head location to screenspace */
344                 if (x0 != IS_CLIPPED) {
345                         points_proj_tot++;
346                         if (BLI_rcti_isect_pt(data->rect, x0, y0) &&
347                             BLI_lasso_is_point_inside(data->mcords, data->moves, x0, y0, INT_MAX))
348                         {
349                                 is_point_done = true;
350                         }
351                 }
352
353                 /* project tail location to screenspace */
354                 if (x1 != IS_CLIPPED) {
355                         points_proj_tot++;
356                         if (BLI_rcti_isect_pt(data->rect, x1, y1) &&
357                             BLI_lasso_is_point_inside(data->mcords, data->moves, x1, y1, INT_MAX))
358                         {
359                                 is_point_done = true;
360                         }
361                 }
362
363                 /* if one of points selected, we skip the bone itself */
364                 if ((is_point_done == true) ||
365                     ((is_point_done == false) && (points_proj_tot == 2) &&
366                      BLI_lasso_is_edge_inside(data->mcords, data->moves, x0, y0, x1, y1, INT_MAX)))
367                 {
368                         if (data->select) pchan->bone->flag |=  BONE_SELECTED;
369                         else              pchan->bone->flag &= ~BONE_SELECTED;
370                         data->is_changed = true;
371                 }
372                 data->is_changed |= is_point_done;
373         }
374 }
375 static void do_lasso_select_pose(ViewContext *vc, Object *ob, const int mcords[][2], short moves, const bool select)
376 {
377         ViewContext vc_tmp;
378         LassoSelectUserData data;
379         rcti rect;
380
381         if ((ob->type != OB_ARMATURE) || (ob->pose == NULL)) {
382                 return;
383         }
384
385         vc_tmp = *vc;
386         vc_tmp.obact = ob;
387
388         BLI_lasso_boundbox(&rect, mcords, moves);
389
390         view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
391
392         ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
393
394         pose_foreachScreenBone(&vc_tmp, do_lasso_select_pose__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
395
396         if (data.is_changed) {
397                 bArmature *arm = ob->data;
398                 if (arm->flag & ARM_HAS_VIZ_DEPS) {
399                         /* mask modifier ('armature' mode), etc. */
400                         DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
401                 }
402                 /* bone selection status is on armature not object */
403                 DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
404         }
405 }
406
407 static void object_deselect_all_visible(ViewLayer *view_layer)
408 {
409         Base *base;
410
411         for (base = view_layer->object_bases.first; base; base = base->next) {
412                 if (BASE_SELECTABLE(base)) {
413                         ED_object_base_select(base, BA_DESELECT);
414                 }
415         }
416 }
417
418 static void do_lasso_select_objects(
419         ViewContext *vc, const int mcords[][2], const short moves,
420         const bool extend, const bool select)
421 {
422         bool is_pose_mode = vc->obact ? (vc->obact->mode & OB_MODE_POSE) : false;
423         Base *base;
424
425         if (extend == false && select)
426                 object_deselect_all_visible(vc->view_layer);
427
428         for (base = vc->view_layer->object_bases.first; base; base = base->next) {
429                 if (BASE_SELECTABLE(base)) { /* use this to avoid un-needed lasso lookups */
430                         if (((vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ?
431                              (is_pose_mode == false) : true) &&
432                             ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK)
433                         {
434                                 if (BLI_lasso_is_point_inside(mcords, moves, base->sx, base->sy, IS_CLIPPED)) {
435
436                                         ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
437                                 }
438                         }
439                         if (is_pose_mode && (base->object->mode & OB_MODE_POSE)) {
440                                 do_lasso_select_pose(vc, base->object, mcords, moves, select);
441                         }
442                 }
443         }
444 }
445
446 static void do_lasso_select_mesh__doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index))
447 {
448         LassoSelectUserData *data = userData;
449
450         if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
451             BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED))
452         {
453                 BM_vert_select_set(data->vc->em->bm, eve, data->select);
454         }
455 }
456 static void do_lasso_select_mesh__doSelectEdge(
457         void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
458 {
459         LassoSelectUserData *data = userData;
460
461         if (EDBM_backbuf_check(bm_solidoffs + index)) {
462                 const int x0 = screen_co_a[0];
463                 const int y0 = screen_co_a[1];
464                 const int x1 = screen_co_b[0];
465                 const int y1 = screen_co_b[1];
466
467                 if (data->pass == 0) {
468                         if (edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b)  &&
469                             BLI_lasso_is_point_inside(data->mcords, data->moves, x0, y0, IS_CLIPPED) &&
470                             BLI_lasso_is_point_inside(data->mcords, data->moves, x1, y1, IS_CLIPPED))
471                         {
472                                 BM_edge_select_set(data->vc->em->bm, eed, data->select);
473                                 data->is_done = true;
474                         }
475                 }
476                 else {
477                         if (BLI_lasso_is_edge_inside(data->mcords, data->moves, x0, y0, x1, y1, IS_CLIPPED)) {
478                                 BM_edge_select_set(data->vc->em->bm, eed, data->select);
479                         }
480                 }
481         }
482 }
483 static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
484 {
485         LassoSelectUserData *data = userData;
486
487         if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
488             BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED))
489         {
490                 BM_face_select_set(data->vc->em->bm, efa, data->select);
491         }
492 }
493
494 static void do_lasso_select_mesh(
495         ViewContext *vc,
496         const int mcords[][2], short moves, bool extend, bool select)
497 {
498         LassoSelectUserData data;
499         ToolSettings *ts = vc->scene->toolsettings;
500         rcti rect;
501         int bbsel;
502
503         /* set editmesh */
504         vc->em = BKE_editmesh_from_object(vc->obedit);
505
506         BLI_lasso_boundbox(&rect, mcords, moves);
507
508         view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
509
510         if (extend == false && select)
511                 EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT);
512
513         /* for non zbuf projections, don't change the GL state */
514         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
515
516         GPU_matrix_set(vc->rv3d->viewmat);
517         bbsel = EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
518
519         if (ts->selectmode & SCE_SELECT_VERTEX) {
520                 if (bbsel) {
521                         edbm_backbuf_check_and_select_verts(vc->em, select);
522                 }
523                 else {
524                         mesh_foreachScreenVert(vc, do_lasso_select_mesh__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
525                 }
526         }
527         if (ts->selectmode & SCE_SELECT_EDGE) {
528                 /* Does both bbsel and non-bbsel versions (need screen cos for both) */
529                 data.pass = 0;
530                 mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
531
532                 if (data.is_done == false) {
533                         data.pass = 1;
534                         mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
535                 }
536         }
537
538         if (ts->selectmode & SCE_SELECT_FACE) {
539                 if (bbsel) {
540                         edbm_backbuf_check_and_select_faces(vc->em, select);
541                 }
542                 else {
543                         mesh_foreachScreenFace(vc, do_lasso_select_mesh__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
544                 }
545         }
546
547         EDBM_backbuf_free();
548         EDBM_selectmode_flush(vc->em);
549 }
550
551 static void do_lasso_select_curve__doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
552 {
553         LassoSelectUserData *data = userData;
554         Object *obedit = data->vc->obedit;
555         Curve *cu = (Curve *)obedit->data;
556
557         if (BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)) {
558                 if (bp) {
559                         bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
560                 }
561                 else {
562                         if (cu->drawflag & CU_HIDE_HANDLES) {
563                                 /* can only be (beztindex == 0) here since handles are hidden */
564                                 bezt->f1 = bezt->f2 = bezt->f3 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
565                         }
566                         else {
567                                 if (beztindex == 0) {
568                                         bezt->f1 = data->select ? (bezt->f1 | SELECT) : (bezt->f1 & ~SELECT);
569                                 }
570                                 else if (beztindex == 1) {
571                                         bezt->f2 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
572                                 }
573                                 else {
574                                         bezt->f3 = data->select ? (bezt->f3 | SELECT) : (bezt->f3 & ~SELECT);
575                                 }
576                         }
577                 }
578         }
579 }
580
581 static void do_lasso_select_curve(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
582 {
583         LassoSelectUserData data;
584         rcti rect;
585
586         BLI_lasso_boundbox(&rect, mcords, moves);
587
588         view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
589
590         if (extend == false && select) {
591                 Curve *curve = (Curve *) vc->obedit->data;
592                 ED_curve_deselect_all(curve->editnurb);
593         }
594
595         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
596         nurbs_foreachScreenVert(vc, do_lasso_select_curve__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
597         BKE_curve_nurb_vert_active_validate(vc->obedit->data);
598 }
599
600 static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, const float screen_co[2])
601 {
602         LassoSelectUserData *data = userData;
603
604         if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
605             BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED))
606         {
607                 bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
608         }
609 }
610 static void do_lasso_select_lattice(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
611 {
612         LassoSelectUserData data;
613         rcti rect;
614
615         BLI_lasso_boundbox(&rect, mcords, moves);
616
617         view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
618
619         if (extend == false && select)
620                 ED_lattice_flags_set(vc->obedit, 0);
621
622         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
623         lattice_foreachScreenVert(vc, do_lasso_select_lattice__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
624 }
625
626 static void do_lasso_select_armature__doSelectBone(void *userData, struct EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2])
627 {
628         LassoSelectUserData *data = userData;
629         bArmature *arm = data->vc->obedit->data;
630
631         if (data->select ? EBONE_SELECTABLE(arm, ebone) : EBONE_VISIBLE(arm, ebone)) {
632                 bool is_point_done = false;
633                 int points_proj_tot = 0;
634
635                 const int x0 = screen_co_a[0];
636                 const int y0 = screen_co_a[1];
637                 const int x1 = screen_co_b[0];
638                 const int y1 = screen_co_b[1];
639
640                 /* project head location to screenspace */
641                 if (x0 != IS_CLIPPED) {
642                         points_proj_tot++;
643                         if (BLI_rcti_isect_pt(data->rect, x0, y0) &&
644                             BLI_lasso_is_point_inside(data->mcords, data->moves, x0, y0, INT_MAX))
645                         {
646                                 is_point_done = true;
647                                 if (data->select) ebone->flag |=  BONE_ROOTSEL;
648                                 else              ebone->flag &= ~BONE_ROOTSEL;
649                         }
650                 }
651
652                 /* project tail location to screenspace */
653                 if (x1 != IS_CLIPPED) {
654                         points_proj_tot++;
655                         if (BLI_rcti_isect_pt(data->rect, x1, y1) &&
656                             BLI_lasso_is_point_inside(data->mcords, data->moves, x1, y1, INT_MAX))
657                         {
658                                 is_point_done = true;
659                                 if (data->select) ebone->flag |=  BONE_TIPSEL;
660                                 else              ebone->flag &= ~BONE_TIPSEL;
661                         }
662                 }
663
664                 /* if one of points selected, we skip the bone itself */
665                 if ((is_point_done == false) && (points_proj_tot == 2) &&
666                     BLI_lasso_is_edge_inside(data->mcords, data->moves, x0, y0, x1, y1, INT_MAX))
667                 {
668                         if (data->select) ebone->flag |=  (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
669                         else              ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
670                         data->is_changed = true;
671                 }
672
673                 data->is_changed |= is_point_done;
674         }
675 }
676
677 static void do_lasso_select_armature(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
678 {
679         LassoSelectUserData data;
680         rcti rect;
681
682         BLI_lasso_boundbox(&rect, mcords, moves);
683
684         view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
685
686         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
687
688         if (extend == false && select)
689                 ED_armature_edit_deselect_all_visible(vc->obedit);
690
691         armature_foreachScreenBone(vc, do_lasso_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
692
693         if (data.is_changed) {
694                 bArmature *arm = vc->obedit->data;
695                 ED_armature_edit_sync_selection(arm->edbo);
696                 ED_armature_edit_validate_active(arm);
697                 WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obedit);
698         }
699 }
700
701 static void do_lasso_select_mball__doSelectElem(void *userData, struct MetaElem *ml, const float screen_co[2])
702 {
703         LassoSelectUserData *data = userData;
704
705         if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
706             BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], INT_MAX))
707         {
708                 if (data->select) ml->flag |=  SELECT;
709                 else              ml->flag &= ~SELECT;
710                 data->is_changed = true;
711         }
712 }
713 static void do_lasso_select_meta(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
714 {
715         LassoSelectUserData data;
716         rcti rect;
717
718         MetaBall *mb = (MetaBall *)vc->obedit->data;
719
720         if (extend == false && select)
721                 BKE_mball_deselect_all(mb);
722
723         BLI_lasso_boundbox(&rect, mcords, moves);
724
725         view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
726
727         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
728
729         mball_foreachScreenElem(vc, do_lasso_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
730 }
731
732 static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
733 {
734         LassoSelectUserData *data = userData;
735
736         if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
737             BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED))
738         {
739                 SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT);
740         }
741 }
742 static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
743 {
744         const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0;
745         Object *ob = vc->obact;
746         Mesh *me = ob->data;
747         rcti rect;
748
749         if (me == NULL || me->totvert == 0)
750                 return;
751
752         if (extend == false && select)
753                 paintvert_deselect_all_visible(ob, SEL_DESELECT, false);  /* flush selection at the end */
754
755         BLI_lasso_boundbox(&rect, mcords, moves);
756
757         if (use_zbuf) {
758                 bm_vertoffs = me->totvert + 1; /* max index array */
759
760                 EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
761
762                 edbm_backbuf_check_and_select_verts_obmode(me, select);
763
764                 EDBM_backbuf_free();
765         }
766         else {
767                 LassoSelectUserData data;
768
769                 view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
770
771                 ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
772
773                 meshobject_foreachScreenVert(vc, do_lasso_select_meshobject__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
774
775         }
776
777         if (select == false) {
778                 BKE_mesh_mselect_validate(me);
779         }
780         paintvert_flush_flags(ob);
781 }
782 static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
783 {
784         Object *ob = vc->obact;
785         Mesh *me = ob->data;
786         rcti rect;
787
788         if (me == NULL || me->totpoly == 0)
789                 return;
790
791         if (extend == false && select)
792                 paintface_deselect_all_visible(ob, SEL_DESELECT, false);  /* flush selection at the end */
793
794         bm_vertoffs = me->totpoly + 1; /* max index array */
795
796         BLI_lasso_boundbox(&rect, mcords, moves);
797         EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
798
799         edbm_backbuf_check_and_select_tfaces(me, select);
800
801         EDBM_backbuf_free();
802
803         paintface_flush_flags(ob, SELECT);
804 }
805
806 #if 0
807 static void do_lasso_select_node(int mcords[][2], short moves, const bool select)
808 {
809         SpaceNode *snode = sa->spacedata.first;
810
811         bNode *node;
812         rcti rect;
813         int node_cent[2];
814         float node_centf[2];
815
816         BLI_lasso_boundbox(&rect, mcords, moves);
817
818         /* store selection in temp test flag */
819         for (node = snode->edittree->nodes.first; node; node = node->next) {
820                 node_centf[0] = BLI_RCT_CENTER_X(&node->totr);
821                 node_centf[1] = BLI_RCT_CENTER_Y(&node->totr);
822
823                 ipoco_to_areaco_noclip(G.v2d, node_centf, node_cent);
824                 if (BLI_rcti_isect_pt_v(&rect, node_cent) && BLI_lasso_is_point_inside(mcords, moves, node_cent[0], node_cent[1])) {
825                         if (select) {
826                                 node->flag |= SELECT;
827                         }
828                         else {
829                                 node->flag &= ~SELECT;
830                         }
831                 }
832         }
833         BIF_undo_push("Lasso select nodes");
834 }
835 #endif
836
837 static void view3d_lasso_select(
838         bContext *C, ViewContext *vc,
839         const int mcords[][2], short moves,
840         bool extend, bool select)
841 {
842         Object *ob = CTX_data_active_object(C);
843
844         if (vc->obedit == NULL) { /* Object Mode */
845                 if (BKE_paint_select_face_test(ob)) {
846                         do_lasso_select_paintface(vc, mcords, moves, extend, select);
847                 }
848                 else if (BKE_paint_select_vert_test(ob)) {
849                         do_lasso_select_paintvert(vc, mcords, moves, extend, select);
850                 }
851                 else if (ob && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) {
852                         /* pass */
853                 }
854                 else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
855                         PE_lasso_select(C, mcords, moves, extend, select);
856                 }
857                 else {
858                         do_lasso_select_objects(vc, mcords, moves, extend, select);
859                         DEG_id_tag_update(&vc->scene->id, DEG_TAG_SELECT_UPDATE);
860                         WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
861                 }
862         }
863         else { /* Edit Mode */
864
865                 FOREACH_OBJECT_IN_MODE_BEGIN (vc->view_layer, ob->mode, ob_iter) {
866                         ED_view3d_viewcontext_init_object(vc, ob_iter);
867
868                         switch (vc->obedit->type) {
869                                 case OB_MESH:
870                                         do_lasso_select_mesh(vc, mcords, moves, extend, select);
871                                         break;
872                                 case OB_CURVE:
873                                 case OB_SURF:
874                                         do_lasso_select_curve(vc, mcords, moves, extend, select);
875                                         break;
876                                 case OB_LATTICE:
877                                         do_lasso_select_lattice(vc, mcords, moves, extend, select);
878                                         break;
879                                 case OB_ARMATURE:
880                                         do_lasso_select_armature(vc, mcords, moves, extend, select);
881                                         break;
882                                 case OB_MBALL:
883                                         do_lasso_select_meta(vc, mcords, moves, extend, select);
884                                         break;
885                                 default:
886                                         assert(!"lasso select on incorrect object type");
887                                         break;
888                         }
889
890                         DEG_id_tag_update(vc->obedit->data, DEG_TAG_SELECT_UPDATE);
891                         WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc->obedit->data);
892                 }
893                 FOREACH_OBJECT_IN_MODE_END;
894         }
895 }
896
897
898 /* lasso operator gives properties, but since old code works
899  * with short array we convert */
900 static int view3d_lasso_select_exec(bContext *C, wmOperator *op)
901 {
902         ViewContext vc;
903         int mcords_tot;
904         const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
905
906         if (mcords) {
907                 bool extend, select;
908                 view3d_operator_needs_opengl(C);
909
910                 /* setup view context for argument to callbacks */
911                 ED_view3d_viewcontext_init(C, &vc);
912
913                 extend = RNA_boolean_get(op->ptr, "extend");
914                 select = !RNA_boolean_get(op->ptr, "deselect");
915                 view3d_lasso_select(C, &vc, mcords, mcords_tot, extend, select);
916
917                 MEM_freeN((void *)mcords);
918
919                 return OPERATOR_FINISHED;
920         }
921         return OPERATOR_PASS_THROUGH;
922 }
923
924 void VIEW3D_OT_select_lasso(wmOperatorType *ot)
925 {
926         ot->name = "Lasso Select";
927         ot->description = "Select items using lasso selection";
928         ot->idname = "VIEW3D_OT_select_lasso";
929
930         ot->invoke = WM_gesture_lasso_invoke;
931         ot->modal = WM_gesture_lasso_modal;
932         ot->exec = view3d_lasso_select_exec;
933         ot->poll = view3d_selectable_data;
934         ot->cancel = WM_gesture_lasso_cancel;
935
936         /* flags */
937         ot->flag = OPTYPE_UNDO;
938
939         /* properties */
940         WM_operator_properties_gesture_lasso_select(ot);
941 }
942
943 /* ************************** mouse select ************************* */
944
945 /* The max number of menu items in an object select menu */
946 typedef struct SelMenuItemF {
947         char idname[MAX_ID_NAME - 2];
948         int icon;
949 } SelMenuItemF;
950
951 #define SEL_MENU_SIZE   22
952 static SelMenuItemF object_mouse_select_menu_data[SEL_MENU_SIZE];
953
954 /* special (crappy) operator only for menu select */
955 static const EnumPropertyItem *object_select_menu_enum_itemf(
956         bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
957 {
958         EnumPropertyItem *item = NULL, item_tmp = {0};
959         int totitem = 0;
960         int i = 0;
961
962         /* don't need context but avoid docgen using this */
963         if (C == NULL || object_mouse_select_menu_data[i].idname[0] == '\0') {
964                 return DummyRNA_NULL_items;
965         }
966
967         for (; i < SEL_MENU_SIZE && object_mouse_select_menu_data[i].idname[0] != '\0'; i++) {
968                 item_tmp.name = object_mouse_select_menu_data[i].idname;
969                 item_tmp.identifier = object_mouse_select_menu_data[i].idname;
970                 item_tmp.value = i;
971                 item_tmp.icon = object_mouse_select_menu_data[i].icon;
972                 RNA_enum_item_add(&item, &totitem, &item_tmp);
973         }
974
975         RNA_enum_item_end(&item, &totitem);
976         *r_free = true;
977
978         return item;
979 }
980
981 static int object_select_menu_exec(bContext *C, wmOperator *op)
982 {
983         const int name_index = RNA_enum_get(op->ptr, "name");
984         const bool toggle = RNA_boolean_get(op->ptr, "toggle");
985         bool changed = false;
986         const char *name = object_mouse_select_menu_data[name_index].idname;
987
988         if (!toggle) {
989                 CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
990                 {
991                         if ((base->flag & BASE_SELECTED) != 0) {
992                                 ED_object_base_select(base, BA_DESELECT);
993                                 changed = true;
994                         }
995                 }
996                 CTX_DATA_END;
997         }
998
999         CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
1000         {
1001                 /* this is a bit dodjy, there should only be ONE object with this name, but library objects can mess this up */
1002                 if (STREQ(name, base->object->id.name + 2)) {
1003                         ED_object_base_activate(C, base);
1004                         ED_object_base_select(base, BA_SELECT);
1005                         changed = true;
1006                 }
1007         }
1008         CTX_DATA_END;
1009
1010         /* weak but ensures we activate menu again before using the enum */
1011         memset(object_mouse_select_menu_data, 0, sizeof(object_mouse_select_menu_data));
1012
1013         /* undo? */
1014         if (changed) {
1015                 Scene *scene = CTX_data_scene(C);
1016                 DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
1017                 WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
1018                 return OPERATOR_FINISHED;
1019         }
1020         else {
1021                 return OPERATOR_CANCELLED;
1022         }
1023 }
1024
1025 void VIEW3D_OT_select_menu(wmOperatorType *ot)
1026 {
1027         PropertyRNA *prop;
1028
1029         /* identifiers */
1030         ot->name = "Select Menu";
1031         ot->description = "Menu object selection";
1032         ot->idname = "VIEW3D_OT_select_menu";
1033
1034         /* api callbacks */
1035         ot->invoke = WM_menu_invoke;
1036         ot->exec = object_select_menu_exec;
1037
1038         /* flags */
1039         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1040
1041         /* keyingset to use (dynamic enum) */
1042         prop = RNA_def_enum(ot->srna, "name", DummyRNA_NULL_items, 0, "Object Name", "");
1043         RNA_def_enum_funcs(prop, object_select_menu_enum_itemf);
1044         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_ENUM_NO_TRANSLATE);
1045         ot->prop = prop;
1046
1047         RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle selection instead of deselecting everything first");
1048 }
1049
1050 static void deselectall_except(ViewLayer *view_layer, Base *b)   /* deselect all except b */
1051 {
1052         for (Base *base = view_layer->object_bases.first; base; base = base->next) {
1053                 if (base->flag & BASE_SELECTED) {
1054                         if (b != base) {
1055                                 ED_object_base_select(base, BA_DESELECT);
1056                         }
1057                 }
1058         }
1059 }
1060
1061 static Base *object_mouse_select_menu(
1062         bContext *C, ViewContext *vc, unsigned int *buffer, int hits,
1063         const int mval[2], bool toggle)
1064 {
1065         short baseCount = 0;
1066         bool ok;
1067         LinkNode *linklist = NULL;
1068         const int object_type_exclude_select = (
1069                 vc->v3d->object_type_exclude_viewport | vc->v3d->object_type_exclude_select);
1070
1071         /* handle base->object->select_color */
1072         CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
1073         {
1074                 ok = false;
1075
1076                 /* two selection methods, the CTRL select uses max dist of 15 */
1077                 if (buffer) {
1078                         for (int a = 0; a < hits; a++) {
1079                                 /* index was converted */
1080                                 if (base->object->select_color == (buffer[(4 * a) + 3] & ~0xFFFF0000)) {
1081                                         ok = true;
1082                                         break;
1083                                 }
1084                         }
1085                 }
1086                 else {
1087                         if (object_type_exclude_select & (1 << base->object->type)) {
1088                                 continue;
1089                         }
1090                         const int dist = 15 * U.pixelsize;
1091                         if (ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK) {
1092                                 const int delta_px[2] = {base->sx - mval[0], base->sy - mval[1]};
1093                                 if (len_manhattan_v2_int(delta_px) < dist) {
1094                                         ok = true;
1095                                 }
1096                         }
1097                 }
1098
1099                 if (ok) {
1100                         baseCount++;
1101                         BLI_linklist_prepend(&linklist, base);
1102
1103                         if (baseCount == SEL_MENU_SIZE)
1104                                 break;
1105                 }
1106         }
1107         CTX_DATA_END;
1108
1109         if (baseCount == 0) {
1110                 return NULL;
1111         }
1112         if (baseCount == 1) {
1113                 Base *base = (Base *)linklist->link;
1114                 BLI_linklist_free(linklist, NULL);
1115                 return base;
1116         }
1117         else {
1118                 /* UI, full in static array values that we later use in an enum function */
1119                 LinkNode *node;
1120                 int i;
1121
1122                 memset(object_mouse_select_menu_data, 0, sizeof(object_mouse_select_menu_data));
1123
1124                 for (node = linklist, i = 0; node; node = node->next, i++) {
1125                         Base *base = node->link;
1126                         Object *ob = base->object;
1127                         const char *name = ob->id.name + 2;
1128
1129                         BLI_strncpy(object_mouse_select_menu_data[i].idname, name, MAX_ID_NAME - 2);
1130                         object_mouse_select_menu_data[i].icon = UI_icon_from_id(&ob->id);
1131                 }
1132
1133                 {
1134                         wmOperatorType *ot = WM_operatortype_find("VIEW3D_OT_select_menu", false);
1135                         PointerRNA ptr;
1136
1137                         WM_operator_properties_create_ptr(&ptr, ot);
1138                         RNA_boolean_set(&ptr, "toggle", toggle);
1139                         WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
1140                         WM_operator_properties_free(&ptr);
1141                 }
1142
1143                 BLI_linklist_free(linklist, NULL);
1144                 return NULL;
1145         }
1146 }
1147
1148 static bool selectbuffer_has_bones(const uint *buffer, const uint hits)
1149 {
1150         unsigned int i;
1151         for (i = 0; i < hits; i++) {
1152                 if (buffer[(4 * i) + 3] & 0xFFFF0000) {
1153                         return true;
1154                 }
1155         }
1156         return false;
1157 }
1158
1159 /* utility function for mixed_bones_object_selectbuffer */
1160 static int selectbuffer_ret_hits_15(unsigned int *UNUSED(buffer), const int hits15)
1161 {
1162         return hits15;
1163 }
1164
1165 static int selectbuffer_ret_hits_9(unsigned int *buffer, const int hits15, const int hits9)
1166 {
1167         const int offs = 4 * hits15;
1168         memcpy(buffer, buffer + offs, 4 * hits9 * sizeof(unsigned int));
1169         return hits9;
1170 }
1171
1172 static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits15, const int hits9, const int hits5)
1173 {
1174         const int offs = 4 * hits15 + 4 * hits9;
1175         memcpy(buffer, buffer + offs, 4 * hits5  * sizeof(unsigned int));
1176         return hits5;
1177 }
1178
1179 /* we want a select buffer with bones, if there are... */
1180 /* so check three selection levels and compare */
1181 static int mixed_bones_object_selectbuffer(
1182         ViewContext *vc, unsigned int *buffer, const int mval[2],
1183         bool use_cycle, bool enumerate, eV3DSelectObjectFilter select_filter,
1184         bool *r_do_nearest)
1185 {
1186         rcti rect;
1187         int hits15, hits9 = 0, hits5 = 0;
1188         bool has_bones15 = false, has_bones9 = false, has_bones5 = false;
1189         static int last_mval[2] = {-100, -100};
1190         bool do_nearest = false;
1191         View3D *v3d = vc->v3d;
1192
1193         /* define if we use solid nearest select or not */
1194         if (use_cycle) {
1195                 if (v3d->shading.type > OB_WIRE) {
1196                         do_nearest = true;
1197                         if (len_manhattan_v2v2_int(mval, last_mval) < 3) {
1198                                 do_nearest = false;
1199                         }
1200                 }
1201                 copy_v2_v2_int(last_mval, mval);
1202         }
1203         else {
1204                 if (v3d->shading.type > OB_WIRE) {
1205                         do_nearest = true;
1206                 }
1207         }
1208
1209         if (r_do_nearest) {
1210                 *r_do_nearest = do_nearest;
1211         }
1212
1213         do_nearest = do_nearest && !enumerate;
1214
1215         const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL);
1216         int hits = 0;
1217
1218         /* we _must_ end cache before return, use 'goto finally' */
1219         view3d_opengl_select_cache_begin();
1220
1221         BLI_rcti_init_pt_radius(&rect, mval, 14);
1222         hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter);
1223         if (hits15 == 1) {
1224                 hits = selectbuffer_ret_hits_15(buffer, hits15);
1225                 goto finally;
1226         }
1227         else if (hits15 > 0) {
1228                 int offs;
1229                 has_bones15 = selectbuffer_has_bones(buffer, hits15);
1230
1231                 offs = 4 * hits15;
1232                 BLI_rcti_init_pt_radius(&rect, mval, 9);
1233                 hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter);
1234                 if (hits9 == 1) {
1235                         hits = selectbuffer_ret_hits_9(buffer, hits15, hits9);
1236                         goto finally;
1237                 }
1238                 else if (hits9 > 0) {
1239                         has_bones9 = selectbuffer_has_bones(buffer + offs, hits9);
1240
1241                         offs += 4 * hits9;
1242                         BLI_rcti_init_pt_radius(&rect, mval, 5);
1243                         hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter);
1244                         if (hits5 == 1) {
1245                                 hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
1246                                 goto finally;
1247                         }
1248                         else if (hits5 > 0) {
1249                                 has_bones5 = selectbuffer_has_bones(buffer + offs, hits5);
1250                         }
1251                 }
1252
1253                 if      (has_bones5)  { hits = selectbuffer_ret_hits_5(buffer,  hits15, hits9, hits5); goto finally; }
1254                 else if (has_bones9)  { hits = selectbuffer_ret_hits_9(buffer,  hits15, hits9); goto finally; }
1255                 else if (has_bones15) { hits = selectbuffer_ret_hits_15(buffer, hits15); goto finally; }
1256
1257                 if      (hits5 > 0) { hits = selectbuffer_ret_hits_5(buffer,  hits15, hits9, hits5); goto finally; }
1258                 else if (hits9 > 0) { hits = selectbuffer_ret_hits_9(buffer,  hits15, hits9); goto finally; }
1259                 else                { hits = selectbuffer_ret_hits_15(buffer, hits15); goto finally; }
1260         }
1261
1262 finally:
1263         view3d_opengl_select_cache_end();
1264
1265         if (vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
1266                 const bool is_pose_mode = (vc->obact && vc->obact->mode & OB_MODE_POSE);
1267                 struct {
1268                         uint data[4];
1269                 } *buffer4 = (void *)buffer;
1270                 uint j = 0;
1271                 for (uint i = 0; i < hits; i++) {
1272                         if (((buffer4[i].data[3] & 0xFFFF0000) != 0) == is_pose_mode) {
1273                                 if (i != j) {
1274                                         buffer4[j] = buffer4[i];
1275                                 }
1276                                 j++;
1277                         }
1278                 }
1279                 hits = j;
1280         }
1281
1282         return hits;
1283 }
1284
1285 /* returns basact */
1286 static Base *mouse_select_eval_buffer(
1287         ViewContext *vc, const uint *buffer, int hits,
1288         Base *startbase, bool has_bones, bool do_nearest)
1289 {
1290         ViewLayer *view_layer = vc->view_layer;
1291         Base *base, *basact = NULL;
1292         int a;
1293
1294         if (do_nearest) {
1295                 unsigned int min = 0xFFFFFFFF;
1296                 int selcol = 0, notcol = 0;
1297
1298
1299                 if (has_bones) {
1300                         /* we skip non-bone hits */
1301                         for (a = 0; a < hits; a++) {
1302                                 if (min > buffer[4 * a + 1] && (buffer[4 * a + 3] & 0xFFFF0000) ) {
1303                                         min = buffer[4 * a + 1];
1304                                         selcol = buffer[4 * a + 3] & 0xFFFF;
1305                                 }
1306                         }
1307                 }
1308                 else {
1309                         /* only exclude active object when it is selected... */
1310                         if (BASACT(view_layer) && (BASACT(view_layer)->flag & BASE_SELECTED) && hits > 1) {
1311                                 notcol = BASACT(view_layer)->object->select_color;
1312                         }
1313
1314                         for (a = 0; a < hits; a++) {
1315                                 if (min > buffer[4 * a + 1] && notcol != (buffer[4 * a + 3] & 0xFFFF)) {
1316                                         min = buffer[4 * a + 1];
1317                                         selcol = buffer[4 * a + 3] & 0xFFFF;
1318                                 }
1319                         }
1320                 }
1321
1322                 base = FIRSTBASE(view_layer);
1323                 while (base) {
1324                         if (BASE_SELECTABLE(base)) {
1325                                 if (base->object->select_color == selcol) break;
1326                         }
1327                         base = base->next;
1328                 }
1329                 if (base) basact = base;
1330         }
1331         else {
1332
1333                 base = startbase;
1334                 while (base) {
1335                         /* skip objects with select restriction, to prevent prematurely ending this loop
1336                          * with an un-selectable choice */
1337                         if ((base->flag & BASE_SELECTABLE) == 0) {
1338                                 base = base->next;
1339                                 if (base == NULL) base = FIRSTBASE(view_layer);
1340                                 if (base == startbase) break;
1341                         }
1342
1343                         if (BASE_SELECTABLE(base)) {
1344                                 for (a = 0; a < hits; a++) {
1345                                         if (has_bones) {
1346                                                 /* skip non-bone objects */
1347                                                 if ((buffer[4 * a + 3] & 0xFFFF0000)) {
1348                                                         if (base->object->select_color == (buffer[(4 * a) + 3] & 0xFFFF))
1349                                                                 basact = base;
1350                                                 }
1351                                         }
1352                                         else {
1353                                                 if (base->object->select_color == (buffer[(4 * a) + 3] & 0xFFFF))
1354                                                         basact = base;
1355                                         }
1356                                 }
1357                         }
1358
1359                         if (basact) break;
1360
1361                         base = base->next;
1362                         if (base == NULL) base = FIRSTBASE(view_layer);
1363                         if (base == startbase) break;
1364                 }
1365         }
1366
1367         return basact;
1368 }
1369
1370 /* mval comes from event->mval, only use within region handlers */
1371 Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
1372 {
1373         ViewContext vc;
1374         Base *basact = NULL;
1375         unsigned int buffer[MAXPICKBUF];
1376         int hits;
1377         bool do_nearest;
1378
1379         /* setup view context for argument to callbacks */
1380         view3d_operator_needs_opengl(C);
1381
1382         ED_view3d_viewcontext_init(C, &vc);
1383
1384         hits = mixed_bones_object_selectbuffer(
1385                 &vc, buffer, mval,
1386                 false, false, VIEW3D_SELECT_FILTER_NOP,
1387                 &do_nearest);
1388
1389         if (hits > 0) {
1390                 const bool has_bones = selectbuffer_has_bones(buffer, hits);
1391                 basact = mouse_select_eval_buffer(&vc, buffer, hits, vc.view_layer->object_bases.first, has_bones, do_nearest);
1392         }
1393
1394         return basact;
1395 }
1396
1397 static void deselect_all_tracks(MovieTracking *tracking)
1398 {
1399         MovieTrackingObject *object;
1400
1401         object = tracking->objects.first;
1402         while (object) {
1403                 ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
1404                 MovieTrackingTrack *track = tracksbase->first;
1405
1406                 while (track) {
1407                         BKE_tracking_track_deselect(track, TRACK_AREA_ALL);
1408
1409                         track = track->next;
1410                 }
1411
1412                 object = object->next;
1413         }
1414 }
1415
1416 /* mval is region coords */
1417 static bool ed_object_select_pick(
1418         bContext *C, const int mval[2],
1419         bool extend, bool deselect, bool toggle, bool obcenter, bool enumerate, bool object)
1420 {
1421         ViewContext vc;
1422         ARegion *ar = CTX_wm_region(C);
1423         Scene *scene = CTX_data_scene(C);
1424         ViewLayer *view_layer = CTX_data_view_layer(C);
1425         Base *base, *startbase = NULL, *basact = NULL, *oldbasact = BASACT(view_layer);
1426         const eObjectMode object_mode = oldbasact ? oldbasact->object->mode : OB_MODE_OBJECT;
1427         bool is_obedit;
1428         float dist = ED_view3d_select_dist_px() * 1.3333f;
1429         bool retval = false;
1430         int hits;
1431         const float mval_fl[2] = {(float)mval[0], (float)mval[1]};
1432
1433         /* setup view context for argument to callbacks */
1434         ED_view3d_viewcontext_init(C, &vc);
1435
1436         is_obedit = (vc.obedit != NULL);
1437         if (object) {
1438                 /* signal for view3d_opengl_select to skip editmode objects */
1439                 vc.obedit = NULL;
1440         }
1441
1442         /* In pose mode we don't want to mess with object selection. */
1443         const bool is_pose_mode = (vc.obact && vc.obact->mode & OB_MODE_POSE);
1444
1445         /* always start list from basact in wire mode */
1446         startbase =  FIRSTBASE(view_layer);
1447         if (BASACT(view_layer) && BASACT(view_layer)->next) startbase = BASACT(view_layer)->next;
1448
1449         /* This block uses the control key to make the object selected by its center point rather than its contents */
1450         /* in editmode do not activate */
1451         if (obcenter) {
1452
1453                 /* note; shift+alt goes to group-flush-selecting */
1454                 if (enumerate) {
1455                         basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, toggle);
1456                 }
1457                 else {
1458                         const int object_type_exclude_select = (
1459                                 vc.v3d->object_type_exclude_viewport | vc.v3d->object_type_exclude_select);
1460                         base = startbase;
1461                         while (base) {
1462                                 if (BASE_SELECTABLE(base) &&
1463                                     ((object_type_exclude_select & (1 << base->object->type)) == 0))
1464                                 {
1465                                         float screen_co[2];
1466                                         if (ED_view3d_project_float_global(
1467                                                     ar, base->object->obmat[3], screen_co,
1468                                                     V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
1469                                         {
1470                                                 float dist_temp = len_manhattan_v2v2(mval_fl, screen_co);
1471                                                 if (base == BASACT(view_layer)) dist_temp += 10.0f;
1472                                                 if (dist_temp < dist) {
1473                                                         dist = dist_temp;
1474                                                         basact = base;
1475                                                 }
1476                                         }
1477                                 }
1478                                 base = base->next;
1479
1480                                 if (base == NULL) base = FIRSTBASE(view_layer);
1481                                 if (base == startbase) break;
1482                         }
1483                 }
1484                 if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
1485                         if (is_obedit == false) {
1486                                 if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) {
1487                                         if (object_mode == OB_MODE_OBJECT) {
1488                                                 struct Main *bmain = CTX_data_main(C);
1489                                                 ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object);
1490                                         }
1491                                         if (!BKE_object_is_mode_compat(basact->object, object_mode)) {
1492                                                 basact = NULL;
1493                                         }
1494                                 }
1495                         }
1496                 }
1497         }
1498         else {
1499                 unsigned int buffer[MAXPICKBUF];
1500                 bool do_nearest;
1501
1502                 // TIMEIT_START(select_time);
1503
1504                 /* if objects have posemode set, the bones are in the same selection buffer */
1505                 const eV3DSelectObjectFilter select_filter = (
1506                         (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ?
1507                         VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK : VIEW3D_SELECT_FILTER_NOP);
1508                 hits = mixed_bones_object_selectbuffer(
1509                         &vc, buffer, mval,
1510                         true, enumerate, select_filter,
1511                         &do_nearest);
1512
1513                 // TIMEIT_END(select_time);
1514
1515                 if (hits > 0) {
1516                         /* note: bundles are handling in the same way as bones */
1517                         const bool has_bones = selectbuffer_has_bones(buffer, hits);
1518
1519                         /* note; shift+alt goes to group-flush-selecting */
1520                         if (enumerate) {
1521                                 basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, toggle);
1522                         }
1523                         else {
1524                                 basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, has_bones, do_nearest);
1525                         }
1526
1527                         if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
1528                                 if (is_obedit == false) {
1529                                         if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) {
1530                                                 if (object_mode == OB_MODE_OBJECT) {
1531                                                         struct Main *bmain = CTX_data_main(C);
1532                                                         ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object);
1533                                                 }
1534                                                 if (!BKE_object_is_mode_compat(basact->object, object_mode)) {
1535                                                         basact = NULL;
1536                                                 }
1537                                         }
1538                                 }
1539                         }
1540
1541                         if (has_bones && basact) {
1542                                 if (basact->object->type == OB_CAMERA) {
1543                                         if (BASACT(view_layer) == basact) {
1544                                                 int i, hitresult;
1545                                                 bool changed = false;
1546
1547                                                 for (i = 0; i < hits; i++) {
1548                                                         hitresult = buffer[3 + (i * 4)];
1549
1550                                                         /* if there's bundles in buffer select bundles first,
1551                                                          * so non-camera elements should be ignored in buffer */
1552                                                         if (basact->object->select_color != (hitresult & 0xFFFF)) {
1553                                                                 continue;
1554                                                         }
1555
1556                                                         /* index of bundle is 1<<16-based. if there's no "bone" index
1557                                                          * in height word, this buffer value belongs to camera. not to bundle */
1558                                                         if (buffer[4 * i + 3] & 0xFFFF0000) {
1559                                                                 MovieClip *clip = BKE_object_movieclip_get(scene, basact->object, false);
1560                                                                 MovieTracking *tracking = &clip->tracking;
1561                                                                 ListBase *tracksbase;
1562                                                                 MovieTrackingTrack *track;
1563
1564                                                                 track = BKE_tracking_track_get_indexed(&clip->tracking, hitresult >> 16, &tracksbase);
1565
1566                                                                 if (TRACK_SELECTED(track) && extend) {
1567                                                                         changed = false;
1568                                                                         BKE_tracking_track_deselect(track, TRACK_AREA_ALL);
1569                                                                 }
1570                                                                 else {
1571                                                                         int oldsel = TRACK_SELECTED(track) ? 1 : 0;
1572                                                                         if (!extend)
1573                                                                                 deselect_all_tracks(tracking);
1574
1575                                                                         BKE_tracking_track_select(tracksbase, track, TRACK_AREA_ALL, extend);
1576
1577                                                                         if (oldsel != (TRACK_SELECTED(track) ? 1 : 0))
1578                                                                                 changed = true;
1579                                                                 }
1580
1581                                                                 basact->flag |= BASE_SELECTED;
1582                                                                 BKE_scene_object_base_flag_sync_from_base(basact);
1583
1584                                                                 retval = true;
1585
1586                                                                 DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
1587                                                                 WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, track);
1588                                                                 WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
1589
1590                                                                 break;
1591                                                         }
1592                                                 }
1593
1594                                                 if (!changed) {
1595                                                         /* fallback to regular object selection if no new bundles were selected,
1596                                                          * allows to select object parented to reconstruction object */
1597                                                         basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, 0, do_nearest);
1598                                                 }
1599                                         }
1600                                 }
1601                                 else if (ED_armature_pose_select_pick_with_buffer(
1602                                                  view_layer, basact, buffer, hits, extend, deselect, toggle, do_nearest))
1603                                 {
1604                                         /* then bone is found */
1605
1606                                         /* we make the armature selected:
1607                                          * not-selected active object in posemode won't work well for tools */
1608                                         basact->flag |= BASE_SELECTED;
1609                                         BKE_scene_object_base_flag_sync_from_base(basact);
1610
1611                                         retval = true;
1612                                         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object);
1613                                         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, basact->object);
1614
1615                                         /* in weightpaint, we use selected bone to select vertexgroup, so no switch to new active object */
1616                                         if (BASACT(view_layer) && (BASACT(view_layer)->object->mode & OB_MODE_WEIGHT_PAINT)) {
1617                                                 /* prevent activating */
1618                                                 basact = NULL;
1619                                         }
1620
1621                                 }
1622                                 /* prevent bone selecting to pass on to object selecting */
1623                                 if (basact == BASACT(view_layer))
1624                                         basact = NULL;
1625                         }
1626                 }
1627         }
1628
1629         if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
1630                 /* Disallow switching modes,
1631                  * special exception for edit-mode - vertex-parent operator. */
1632                 if (is_obedit == false) {
1633                         if (oldbasact && basact) {
1634                                 if ((oldbasact->object->mode != basact->object->mode) &&
1635                                     (oldbasact->object->mode & basact->object->mode) == 0)
1636                                 {
1637                                         basact = NULL;
1638                                 }
1639                         }
1640                 }
1641         }
1642
1643         /* so, do we have something selected? */
1644         if (basact) {
1645                 retval = true;
1646
1647                 if (vc.obedit) {
1648                         /* only do select */
1649                         deselectall_except(view_layer, basact);
1650                         ED_object_base_select(basact, BA_SELECT);
1651                 }
1652                 /* also prevent making it active on mouse selection */
1653                 else if (BASE_SELECTABLE(basact)) {
1654                         if (extend) {
1655                                 ED_object_base_select(basact, BA_SELECT);
1656                         }
1657                         else if (deselect) {
1658                                 ED_object_base_select(basact, BA_DESELECT);
1659                         }
1660                         else if (toggle) {
1661                                 if (basact->flag & BASE_SELECTED) {
1662                                         if (basact == oldbasact) {
1663                                                 ED_object_base_select(basact, BA_DESELECT);
1664                                         }
1665                                 }
1666                                 else {
1667                                         ED_object_base_select(basact, BA_SELECT);
1668                                 }
1669                         }
1670                         else {
1671                                 /* When enabled, this puts other objects out of multi pose-mode. */
1672                                 if (is_pose_mode == false) {
1673                                         deselectall_except(view_layer, basact);
1674                                         ED_object_base_select(basact, BA_SELECT);
1675                                 }
1676                         }
1677
1678                         if ((oldbasact != basact) && (is_obedit == false)) {
1679                                 ED_object_base_activate(C, basact); /* adds notifier */
1680                         }
1681
1682                         /* Set special modes for grease pencil
1683                            The grease pencil modes are not real modes, but a hack to make the interface
1684                            consistent, so need some tricks to keep UI synchronized */
1685                         // XXX: This stuff neeeds reviewing (Aligorith)
1686                         if (false &&
1687                             (((oldbasact) && oldbasact->object->type == OB_GPENCIL) ||
1688                              (basact->object->type == OB_GPENCIL)))
1689                         {
1690                                 /* set cursor */
1691                                 if (ELEM(basact->object->mode,
1692                                          OB_MODE_GPENCIL_PAINT,
1693                                          OB_MODE_GPENCIL_SCULPT,
1694                                          OB_MODE_GPENCIL_WEIGHT))
1695                                 {
1696                                         ED_gpencil_toggle_brush_cursor(C, true, NULL);
1697                                 }
1698                                 else {
1699                                         /* TODO: maybe is better use restore */
1700                                         ED_gpencil_toggle_brush_cursor(C, false, NULL);
1701                                 }
1702                         }
1703                 }
1704
1705                 DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
1706                 WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
1707         }
1708
1709         return retval;
1710 }
1711
1712 /* ********************  border and circle ************************************** */
1713
1714 typedef struct BoxSelectUserData {
1715         ViewContext *vc;
1716         const rcti *rect;
1717         const rctf *rect_fl;
1718         rctf       _rect_fl;
1719         bool select;
1720
1721         /* runtime */
1722         int pass;
1723         bool is_done;
1724         bool is_changed;
1725 } BoxSelectUserData;
1726
1727 static void view3d_userdata_boxselect_init(
1728         BoxSelectUserData *r_data,
1729         ViewContext *vc, const rcti *rect, const bool select)
1730 {
1731         r_data->vc = vc;
1732
1733         r_data->rect = rect;
1734         r_data->rect_fl = &r_data->_rect_fl;
1735         BLI_rctf_rcti_copy(&r_data->_rect_fl, rect);
1736
1737         r_data->select = select;
1738
1739         /* runtime */
1740         r_data->pass = 0;
1741         r_data->is_done = false;
1742         r_data->is_changed = false;
1743 }
1744
1745 bool edge_inside_circle(const float cent[2], float radius, const float screen_co_a[2], const float screen_co_b[2])
1746 {
1747         const float radius_squared = radius * radius;
1748         return (dist_squared_to_line_segment_v2(cent, screen_co_a, screen_co_b) < radius_squared);
1749 }
1750
1751 static void do_paintvert_box_select__doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
1752 {
1753         BoxSelectUserData *data = userData;
1754
1755         if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co)) {
1756                 SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT);
1757         }
1758 }
1759 static int do_paintvert_box_select(
1760         ViewContext *vc, rcti *rect, bool select, bool extend)
1761 {
1762         const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0;
1763         Mesh *me;
1764         MVert *mvert;
1765         struct ImBuf *ibuf;
1766         unsigned int *rt;
1767         int a, index;
1768         char *selar;
1769         const int size[2] = {
1770             BLI_rcti_size_x(rect) + 1,
1771             BLI_rcti_size_y(rect) + 1};
1772
1773         me = vc->obact->data;
1774
1775         if ((me == NULL) || (me->totvert == 0) || (size[0] * size[1] <= 0)) {
1776                 return OPERATOR_CANCELLED;
1777         }
1778
1779         if (extend == false && select)
1780                 paintvert_deselect_all_visible(vc->obact, SEL_DESELECT, false);
1781
1782         if (use_zbuf) {
1783                 selar = MEM_callocN(me->totvert + 1, "selar");
1784                 ED_view3d_backbuf_validate(vc);
1785
1786                 ibuf = IMB_allocImBuf(size[0], size[1], 32, IB_rect);
1787                 rt = ibuf->rect;
1788                 glReadPixels(
1789                         rect->xmin + vc->ar->winrct.xmin,
1790                         rect->ymin + vc->ar->winrct.ymin,
1791                         size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE,  ibuf->rect);
1792                 if (ENDIAN_ORDER == B_ENDIAN) {
1793                         IMB_convert_rgba_to_abgr(ibuf);
1794                 }
1795                 GPU_select_to_index_array(ibuf->rect, size[0] * size[1]);
1796
1797                 a = size[0] * size[1];
1798                 while (a--) {
1799                         if (*rt) {
1800                                 index = *rt;
1801                                 if (index <= me->totvert) {
1802                                         selar[index] = 1;
1803                                 }
1804                         }
1805                         rt++;
1806                 }
1807
1808                 mvert = me->mvert;
1809                 for (a = 1; a <= me->totvert; a++, mvert++) {
1810                         if (selar[a]) {
1811                                 if ((mvert->flag & ME_HIDE) == 0) {
1812                                         if (select) mvert->flag |=  SELECT;
1813                                         else        mvert->flag &= ~SELECT;
1814                                 }
1815                         }
1816                 }
1817
1818                 IMB_freeImBuf(ibuf);
1819                 MEM_freeN(selar);
1820
1821 #ifdef __APPLE__
1822                 glReadBuffer(GL_BACK);
1823 #endif
1824         }
1825         else {
1826                 BoxSelectUserData data;
1827
1828                 view3d_userdata_boxselect_init(&data, vc, rect, select);
1829
1830                 ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
1831
1832                 meshobject_foreachScreenVert(vc, do_paintvert_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
1833         }
1834
1835         if (select == false) {
1836                 BKE_mesh_mselect_validate(me);
1837         }
1838         paintvert_flush_flags(vc->obact);
1839
1840         return OPERATOR_FINISHED;
1841 }
1842
1843 static void do_nurbs_box_select__doSelect(
1844         void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
1845 {
1846         BoxSelectUserData *data = userData;
1847         Object *obedit = data->vc->obedit;
1848         Curve *cu = (Curve *)obedit->data;
1849
1850         if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co)) {
1851                 if (bp) {
1852                         bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
1853                 }
1854                 else {
1855                         if (cu->drawflag & CU_HIDE_HANDLES) {
1856                                 /* can only be (beztindex == 0) here since handles are hidden */
1857                                 bezt->f1 = bezt->f2 = bezt->f3 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
1858                         }
1859                         else {
1860                                 if (beztindex == 0) {
1861                                         bezt->f1 = data->select ? (bezt->f1 | SELECT) : (bezt->f1 & ~SELECT);
1862                                 }
1863                                 else if (beztindex == 1) {
1864                                         bezt->f2 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
1865                                 }
1866                                 else {
1867                                         bezt->f3 = data->select ? (bezt->f3 | SELECT) : (bezt->f3 & ~SELECT);
1868                                 }
1869                         }
1870                 }
1871         }
1872 }
1873 static int do_nurbs_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
1874 {
1875         BoxSelectUserData data;
1876
1877         view3d_userdata_boxselect_init(&data, vc, rect, select);
1878
1879         if (extend == false && select) {
1880                 Curve *curve = (Curve *) vc->obedit->data;
1881                 ED_curve_deselect_all(curve->editnurb);
1882         }
1883
1884         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
1885         nurbs_foreachScreenVert(vc, do_nurbs_box_select__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
1886         BKE_curve_nurb_vert_active_validate(vc->obedit->data);
1887
1888         return OPERATOR_FINISHED;
1889 }
1890
1891 static void do_lattice_box_select__doSelect(void *userData, BPoint *bp, const float screen_co[2])
1892 {
1893         BoxSelectUserData *data = userData;
1894
1895         if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co)) {
1896                 bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
1897         }
1898 }
1899 static int do_lattice_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
1900 {
1901         BoxSelectUserData data;
1902
1903         view3d_userdata_boxselect_init(&data, vc, rect, select);
1904
1905         if (extend == false && select)
1906                 ED_lattice_flags_set(vc->obedit, 0);
1907
1908         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
1909         lattice_foreachScreenVert(vc, do_lattice_box_select__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
1910
1911         return OPERATOR_FINISHED;
1912 }
1913
1914 static void do_mesh_box_select__doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index))
1915 {
1916         BoxSelectUserData *data = userData;
1917
1918         if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co)) {
1919                 BM_vert_select_set(data->vc->em->bm, eve, data->select);
1920         }
1921 }
1922 static void do_mesh_box_select__doSelectEdge(
1923         void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
1924 {
1925         BoxSelectUserData *data = userData;
1926
1927         if (EDBM_backbuf_check(bm_solidoffs + index)) {
1928                 if (data->pass == 0) {
1929                         if (edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b)) {
1930                                 BM_edge_select_set(data->vc->em->bm, eed, data->select);
1931                                 data->is_done = true;
1932                         }
1933                 }
1934                 else {
1935                         if (edge_inside_rect(data->rect_fl, screen_co_a, screen_co_b)) {
1936                                 BM_edge_select_set(data->vc->em->bm, eed, data->select);
1937                         }
1938                 }
1939         }
1940 }
1941 static void do_mesh_box_select__doSelectFace(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
1942 {
1943         BoxSelectUserData *data = userData;
1944
1945         if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co)) {
1946                 BM_face_select_set(data->vc->em->bm, efa, data->select);
1947         }
1948 }
1949 static int do_mesh_box_select(
1950         ViewContext *vc, rcti *rect, bool select, bool extend)
1951 {
1952         BoxSelectUserData data;
1953         ToolSettings *ts = vc->scene->toolsettings;
1954         int bbsel;
1955
1956         view3d_userdata_boxselect_init(&data, vc, rect, select);
1957
1958         if (extend == false && select)
1959                 EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT);
1960
1961         /* for non zbuf projections, don't change the GL state */
1962         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
1963
1964         GPU_matrix_set(vc->rv3d->viewmat);
1965         bbsel = EDBM_backbuf_border_init(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
1966
1967         if (ts->selectmode & SCE_SELECT_VERTEX) {
1968                 if (bbsel) {
1969                         edbm_backbuf_check_and_select_verts(vc->em, select);
1970                 }
1971                 else {
1972                         mesh_foreachScreenVert(vc, do_mesh_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
1973                 }
1974         }
1975         if (ts->selectmode & SCE_SELECT_EDGE) {
1976                 /* Does both bbsel and non-bbsel versions (need screen cos for both) */
1977
1978                 data.pass = 0;
1979                 mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
1980
1981                 if (data.is_done == 0) {
1982                         data.pass = 1;
1983                         mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
1984                 }
1985         }
1986
1987         if (ts->selectmode & SCE_SELECT_FACE) {
1988                 if (bbsel) {
1989                         edbm_backbuf_check_and_select_faces(vc->em, select);
1990                 }
1991                 else {
1992                         mesh_foreachScreenFace(vc, do_mesh_box_select__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
1993                 }
1994         }
1995
1996         EDBM_backbuf_free();
1997
1998         EDBM_selectmode_flush(vc->em);
1999
2000         return OPERATOR_FINISHED;
2001 }
2002
2003 static int do_meta_box_select(
2004         ViewContext *vc,
2005         const rcti *rect, bool select, bool extend)
2006 {
2007         MetaBall *mb = (MetaBall *)vc->obedit->data;
2008         MetaElem *ml;
2009         int a;
2010
2011         unsigned int buffer[MAXPICKBUF];
2012         int hits;
2013
2014         hits = view3d_opengl_select(
2015                 vc, buffer, MAXPICKBUF, rect,
2016                 VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
2017
2018         if (extend == false && select)
2019                 BKE_mball_deselect_all(mb);
2020
2021         for (ml = mb->editelems->first; ml; ml = ml->next) {
2022                 for (a = 0; a < hits; a++) {
2023                         if (ml->selcol1 == buffer[(4 * a) + 3]) {
2024                                 ml->flag |= MB_SCALE_RAD;
2025                                 if (select) ml->flag |= SELECT;
2026                                 else ml->flag &= ~SELECT;
2027                                 break;
2028                         }
2029                         if (ml->selcol2 == buffer[(4 * a) + 3]) {
2030                                 ml->flag &= ~MB_SCALE_RAD;
2031                                 if (select) ml->flag |= SELECT;
2032                                 else ml->flag &= ~SELECT;
2033                                 break;
2034                         }
2035                 }
2036         }
2037
2038         return OPERATOR_FINISHED;
2039 }
2040
2041 static int do_armature_box_select(
2042         ViewContext *vc,
2043         const rcti *rect, bool select, bool extend)
2044 {
2045         int a;
2046
2047         unsigned int buffer[MAXPICKBUF];
2048         int hits;
2049
2050         hits = view3d_opengl_select(
2051                 vc, buffer, MAXPICKBUF, rect,
2052                 VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
2053
2054         uint objects_len = 0;
2055         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(vc->view_layer, &objects_len);
2056
2057         /* clear flag we use to detect point was affected */
2058         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2059                 Object *obedit = objects[ob_index];
2060                 bArmature *arm = obedit->data;
2061                 for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
2062                         ebone->flag &= ~BONE_DONE;
2063                 }
2064         }
2065
2066         if (extend == false && select) {
2067                 ED_armature_edit_deselect_all_visible_multi(objects, objects_len);
2068         }
2069
2070         /* first we only check points inside the border */
2071         for (a = 0; a < hits; a++) {
2072                 int index = buffer[(4 * a) + 3];
2073                 if (index != -1) {
2074                         if ((index & 0xFFFF0000) == 0) {
2075                                 continue;
2076                         }
2077
2078                         EditBone *ebone;
2079                         ED_armature_object_and_ebone_from_select_buffer(objects, objects_len, index, &ebone);
2080                         if ((select == false) || ((ebone->flag & BONE_UNSELECTABLE) == 0)) {
2081                                 if (index & BONESEL_TIP) {
2082                                         ebone->flag |= BONE_DONE;
2083                                         if (select) ebone->flag |= BONE_TIPSEL;
2084                                         else ebone->flag &= ~BONE_TIPSEL;
2085                                 }
2086
2087                                 if (index & BONESEL_ROOT) {
2088                                         ebone->flag |= BONE_DONE;
2089                                         if (select) ebone->flag |= BONE_ROOTSEL;
2090                                         else ebone->flag &= ~BONE_ROOTSEL;
2091                                 }
2092                         }
2093                 }
2094         }
2095
2096         /* now we have to flush tag from parents... */
2097         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2098                 Object *obedit = objects[ob_index];
2099                 bArmature *arm = obedit->data;
2100                 for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
2101                         if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
2102                                 if (ebone->parent->flag & BONE_DONE) {
2103                                         ebone->flag |= BONE_DONE;
2104                                 }
2105                         }
2106                 }
2107         }
2108
2109         /* only select/deselect entire bones when no points where in the rect */
2110         for (a = 0; a < hits; a++) {
2111                 int index = buffer[(4 * a) + 3];
2112                 if (index != -1) {
2113                         if (index & BONESEL_BONE) {
2114                                 EditBone *ebone;
2115                                 ED_armature_object_and_ebone_from_select_buffer(objects, objects_len, index, &ebone);
2116                                 if ((select == false) || ((ebone->flag & BONE_UNSELECTABLE) == 0)) {
2117                                         if (!(ebone->flag & BONE_DONE)) {
2118                                                 if (select) {
2119                                                         ebone->flag |= (BONE_ROOTSEL | BONE_TIPSEL | BONE_SELECTED);
2120                                                 }
2121                                                 else {
2122                                                         ebone->flag &= ~(BONE_ROOTSEL | BONE_TIPSEL | BONE_SELECTED);
2123                                                 }
2124                                         }
2125                                 }
2126                         }
2127                 }
2128         }
2129
2130         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2131                 Object *obedit = objects[ob_index];
2132                 bArmature *arm = obedit->data;
2133                 ED_armature_edit_sync_selection(arm->edbo);
2134         }
2135
2136         MEM_freeN(objects);
2137
2138         return hits > 0 ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
2139 }
2140
2141 /**
2142  * Compare result of 'GPU_select': 'uint[4]',
2143  * needed for when we need to align with object draw-order.
2144  */
2145 static int opengl_bone_select_buffer_cmp(const void *sel_a_p, const void *sel_b_p)
2146 {
2147         /* 4th element is select id */
2148         uint sel_a = ((uint *)sel_a_p)[3];
2149         uint sel_b = ((uint *)sel_b_p)[3];
2150
2151 #ifdef __BIG_ENDIAN__
2152         BLI_endian_switch_uint32(&sel_a);
2153         BLI_endian_switch_uint32(&sel_b);
2154 #endif
2155
2156         if (sel_a < sel_b) {
2157                 return -1;
2158         }
2159         else if (sel_a > sel_b) {
2160                 return 1;
2161         }
2162         else {
2163                 return 0;
2164         }
2165 }
2166
2167 static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, bool select, bool extend)
2168 {
2169         unsigned int *vbuffer = NULL; /* selection buffer */
2170         int bone_only;
2171         int totobj = MAXPICKBUF; /* XXX solve later */
2172         int hits;
2173
2174         if (vc->obact && (vc->obact->mode & OB_MODE_POSE))
2175                 bone_only = 1;
2176         else
2177                 bone_only = 0;
2178
2179         if (extend == false && select) {
2180                 if (bone_only) {
2181                         FOREACH_OBJECT_IN_MODE_BEGIN (vc->view_layer, OB_MODE_POSE, ob_iter) {
2182                                 bArmature *arm = ob_iter->data;
2183                                 for (bPoseChannel *pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) {
2184                                         if (PBONE_VISIBLE(arm, pchan->bone)) {
2185                                                 if ((select == false) || ((pchan->bone->flag & BONE_UNSELECTABLE) == 0)) {
2186                                                         pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
2187                                                 }
2188                                         }
2189                                 }
2190                         }
2191                         FOREACH_OBJECT_IN_MODE_END;
2192                 }
2193                 else {
2194                         object_deselect_all_visible(vc->view_layer);
2195                 }
2196         }
2197
2198         /* selection buffer now has bones potentially too, so we add MAXPICKBUF */
2199         vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(unsigned int), "selection buffer");
2200         const eV3DSelectObjectFilter select_filter = (
2201                 (vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ?
2202                 VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK : VIEW3D_SELECT_FILTER_NOP);
2203         hits = view3d_opengl_select(
2204                 vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect,
2205                 VIEW3D_SELECT_ALL, select_filter);
2206         /*
2207          * LOGIC NOTES (theeth):
2208          * The buffer and ListBase have the same relative order, which makes the selection
2209          * very simple. Loop through both data sets at the same time, if the color
2210          * is the same as the object, we have a hit and can move to the next color
2211          * and object pair, if not, just move to the next object,
2212          * keeping the same color until we have a hit.
2213          */
2214
2215         if (hits > 0) { /* no need to loop if there's no hit */
2216
2217                 /* The draw order doesn't always match the order we populate the engine, see: T51695. */
2218                 qsort(vbuffer, hits, sizeof(uint[4]), opengl_bone_select_buffer_cmp);
2219
2220                 Base **bases = NULL;
2221                 BLI_array_declare(bases);
2222
2223                 for (Base *base = vc->view_layer->object_bases.first; base && hits; base = base->next) {
2224                         if (BASE_SELECTABLE(base)) {
2225                                 if ((base->object->select_color & 0x0000FFFF) != 0) {
2226                                         BLI_array_append(bases, base);
2227                                 }
2228                         }
2229                 }
2230
2231                 for (const uint *col = vbuffer + 3, *col_end = col + (hits * 4); col < col_end; col += 4) {
2232                         Bone *bone;
2233                         Base *base = ED_armature_base_and_bone_from_select_buffer(bases, BLI_array_len(bases), *col, &bone);
2234
2235                         if (base == NULL) {
2236                                 continue;
2237                         }
2238                         /* Loop over contiguous bone hits for 'base'. */
2239                         bool changed = false;
2240                         for (; col != col_end; col += 4) {
2241                                 /* should never fail */
2242                                 if (bone != NULL) {
2243                                         if (select) {
2244                                                 if ((bone->flag & BONE_UNSELECTABLE) == 0) {
2245                                                         bone->flag |= BONE_SELECTED;
2246                                                 }
2247                                         }
2248                                         else {
2249                                                 bArmature *arm = base->object->data;
2250                                                 if ((bone->flag & BONE_UNSELECTABLE) == 0) {
2251                                                         bone->flag &= ~BONE_SELECTED;
2252                                                         if (arm->act_bone == bone)
2253                                                                 arm->act_bone = NULL;
2254                                                 }
2255                                         }
2256                                         changed = true;
2257                                 }
2258                                 else if (!bone_only) {
2259                                         ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
2260                                 }
2261
2262                                 /* Select the next bone if we're not switching bases. */
2263                                 if (col + 4 != col_end) {
2264                                         if ((base->object->select_color & 0x0000FFFF) != (col[4] & 0x0000FFFF)) {
2265                                                 break;
2266                                         }
2267
2268                                         if ((base->object->pose != NULL) && bone_only) {
2269                                                 const uint hit_bone = (col[4] & ~BONESEL_ANY) >> 16;
2270                                                 bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);
2271                                                 bone = pchan ? pchan->bone : NULL;
2272                                         }
2273                                         else {
2274                                                 bone = NULL;
2275                                         }
2276                                 }
2277                         }
2278
2279                         if (changed) {
2280                                 if (base->object && (base->object->type == OB_ARMATURE)) {
2281                                         bArmature *arm = base->object->data;
2282
2283                                         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, base->object);
2284
2285                                         if (vc->obact && arm && (arm->flag & ARM_HAS_VIZ_DEPS)) {
2286                                                 /* mask modifier ('armature' mode), etc. */
2287                                                 DEG_id_tag_update(&vc->obact->id, OB_RECALC_DATA);
2288                                         }
2289
2290                                         /* copy on write tag is needed (for the armature), or else no refresh happens */
2291                                         DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
2292                                 }
2293                         }
2294                 }
2295
2296                 MEM_freeN(bases);
2297
2298                 DEG_id_tag_update(&vc->scene->id, DEG_TAG_SELECT_UPDATE);
2299                 WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
2300         }
2301         MEM_freeN(vbuffer);
2302
2303         return hits > 0 ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
2304 }
2305
2306 static int view3d_borderselect_exec(bContext *C, wmOperator *op)
2307 {
2308         ViewContext vc;
2309         rcti rect;
2310         bool extend;
2311         bool select;
2312
2313         int ret = OPERATOR_CANCELLED;
2314
2315         view3d_operator_needs_opengl(C);
2316
2317         /* setup view context for argument to callbacks */
2318         ED_view3d_viewcontext_init(C, &vc);
2319
2320         select = !RNA_boolean_get(op->ptr, "deselect");
2321         extend = RNA_boolean_get(op->ptr, "extend");
2322         WM_operator_properties_border_to_rcti(op, &rect);
2323
2324         if (vc.obedit) {
2325
2326                 FOREACH_OBJECT_IN_MODE_BEGIN (vc.view_layer, vc.obedit->mode, ob_iter) {
2327                         ED_view3d_viewcontext_init_object(&vc, ob_iter);
2328
2329                         switch (vc.obedit->type) {
2330                                 case OB_MESH:
2331                                         vc.em = BKE_editmesh_from_object(vc.obedit);
2332                                         ret |= do_mesh_box_select(&vc, &rect, select, extend);
2333                                         if (ret & OPERATOR_FINISHED) {
2334                                                 DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
2335                                                 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
2336                                         }
2337                                         break;
2338                                 case OB_CURVE:
2339                                 case OB_SURF:
2340                                         ret |= do_nurbs_box_select(&vc, &rect, select, extend);
2341                                         if (ret & OPERATOR_FINISHED) {
2342                                                 DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
2343                                                 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
2344                                         }
2345                                         break;
2346                                 case OB_MBALL:
2347                                         ret |= do_meta_box_select(&vc, &rect, select, extend);
2348                                         if (ret & OPERATOR_FINISHED) {
2349                                                 DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
2350                                                 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
2351                                         }
2352                                         break;
2353                                 case OB_ARMATURE:
2354                                         ret |= do_armature_box_select(&vc, &rect, select, extend);
2355                                         if (ret & OPERATOR_FINISHED) {
2356                                                 DEG_id_tag_update(&vc.obedit->id, DEG_TAG_SELECT_UPDATE);
2357                                                 WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit);
2358                                         }
2359                                         break;
2360                                 case OB_LATTICE:
2361                                         ret |= do_lattice_box_select(&vc, &rect, select, extend);
2362                                         if (ret & OPERATOR_FINISHED) {
2363                                                 DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
2364                                                 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
2365                                         }
2366                                         break;
2367                                 default:
2368                                         assert(!"border select on incorrect object type");
2369                                         break;
2370                         }
2371                 }
2372                 FOREACH_OBJECT_IN_MODE_END;
2373         }
2374         else {  /* no editmode, unified for bones and objects */
2375                 if (vc.obact && vc.obact->mode & OB_MODE_SCULPT) {
2376                         ret |= ED_sculpt_mask_box_select(C, &vc, &rect, select, extend);
2377                 }
2378                 else if (vc.obact && BKE_paint_select_face_test(vc.obact)) {
2379                         ret |= do_paintface_box_select(&vc, &rect, select, extend);
2380                 }
2381                 else if (vc.obact && BKE_paint_select_vert_test(vc.obact)) {
2382                         ret |= do_paintvert_box_select(&vc, &rect, select, extend);
2383                 }
2384                 else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) {
2385                         ret |= PE_border_select(C, &rect, select, extend);
2386                 }
2387                 else { /* object mode with none active */
2388                         ret |= do_object_pose_box_select(C, &vc, &rect, select, extend);
2389                 }
2390         }
2391
2392         if (ret & OPERATOR_FINISHED) {
2393                 ret = OPERATOR_FINISHED;
2394         }
2395         else {
2396                 ret = OPERATOR_CANCELLED;
2397         }
2398
2399         return ret;
2400 }
2401
2402
2403 /* *****************Selection Operators******************* */
2404
2405 /* ****** Border Select ****** */
2406 void VIEW3D_OT_select_border(wmOperatorType *ot)
2407 {
2408         /* identifiers */
2409         ot->name = "Border Select";
2410         ot->description = "Select items using border selection";
2411         ot->idname = "VIEW3D_OT_select_border";
2412
2413         /* api callbacks */
2414         ot->invoke = WM_gesture_border_invoke;
2415         ot->exec = view3d_borderselect_exec;
2416         ot->modal = WM_gesture_border_modal;
2417         ot->poll = view3d_selectable_data;
2418         ot->cancel = WM_gesture_border_cancel;
2419
2420         /* flags */
2421         ot->flag = OPTYPE_UNDO;
2422
2423         /* rna */
2424         WM_operator_properties_gesture_border_select(ot);
2425 }
2426
2427
2428 /* mouse selection in weight paint */
2429 /* gets called via generic mouse select operator */
2430 static bool ed_wpaint_vertex_select_pick(
2431         bContext *C, const int mval[2],
2432         bool extend, bool deselect, bool toggle, Object *obact)
2433 {
2434         View3D *v3d = CTX_wm_view3d(C);
2435         const bool use_zbuf = (v3d->flag & V3D_ZBUF_SELECT) != 0;
2436
2437         Mesh *me = obact->data; /* already checked for NULL */
2438         unsigned int index = 0;
2439         MVert *mv;
2440
2441         if (ED_mesh_pick_vert(C, obact, mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE, use_zbuf)) {
2442                 mv = &me->mvert[index];
2443                 if (extend) {
2444                         mv->flag |= SELECT;
2445                 }
2446                 else if (deselect) {
2447                         mv->flag &= ~SELECT;
2448                 }
2449                 else if (toggle) {
2450                         mv->flag ^= SELECT;
2451                 }
2452                 else {
2453                         paintvert_deselect_all_visible(obact, SEL_DESELECT, false);
2454                         mv->flag |= SELECT;
2455                 }
2456
2457                 /* update mselect */
2458                 if (mv->flag & SELECT) {
2459                         BKE_mesh_mselect_active_set(me, index, ME_VSEL);
2460                 }
2461                 else {
2462                         BKE_mesh_mselect_validate(me);
2463                 }
2464
2465                 paintvert_flush_flags(obact);
2466                 DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE);
2467                 WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
2468                 return true;
2469         }
2470         return false;
2471 }
2472
2473 /* ****** Mouse Select ****** */
2474
2475
2476 static int view3d_select_exec(bContext *C, wmOperator *op)
2477 {
2478         Object *obedit = CTX_data_edit_object(C);
2479         Object *obact = CTX_data_active_object(C);
2480         bool extend = RNA_boolean_get(op->ptr, "extend");
2481         bool deselect = RNA_boolean_get(op->ptr, "deselect");
2482         bool toggle = RNA_boolean_get(op->ptr, "toggle");
2483         bool center = RNA_boolean_get(op->ptr, "center");
2484         bool enumerate = RNA_boolean_get(op->ptr, "enumerate");
2485         /* only force object select for editmode to support vertex parenting,
2486          * or paint-select to allow pose bone select with vert/face select */
2487         bool object = (RNA_boolean_get(op->ptr, "object") &&
2488                        (obedit ||
2489                         BKE_paint_select_elem_test(obact) ||
2490                         /* so its possible to select bones in weightpaint mode (LMB select) */
2491                         (obact && (obact->mode & OB_MODE_WEIGHT_PAINT) && BKE_object_pose_armature_get(obact))));
2492
2493         bool retval = false;
2494         int location[2];
2495
2496         RNA_int_get_array(op->ptr, "location", location);
2497
2498         view3d_operator_needs_opengl(C);
2499
2500         if (object) {
2501                 obedit = NULL;
2502                 obact = NULL;
2503
2504                 /* ack, this is incorrect but to do this correctly we would need an
2505                  * alternative editmode/objectmode keymap, this copies the functionality
2506                  * from 2.4x where Ctrl+Select in editmode does object select only */
2507                 center = false;
2508         }
2509
2510         if (obedit && object == false) {
2511                 if (obedit->type == OB_MESH)
2512                         retval = EDBM_select_pick(C, location, extend, deselect, toggle);
2513                 else if (obedit->type == OB_ARMATURE)
2514                         retval = ED_armature_edit_select_pick(C, location, extend, deselect, toggle);
2515                 else if (obedit->type == OB_LATTICE)
2516                         retval = ED_lattice_select_pick(C, location, extend, deselect, toggle);
2517                 else if (ELEM(obedit->type, OB_CURVE, OB_SURF))
2518                         retval = ED_curve_editnurb_select_pick(C, location, extend, deselect, toggle);
2519                 else if (obedit->type == OB_MBALL)
2520                         retval = ED_mball_select_pick(C, location, extend, deselect, toggle);
2521                 else if (obedit->type == OB_FONT)
2522                         retval = ED_curve_editfont_select_pick(C, location, extend, deselect, toggle);
2523
2524         }
2525         else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT)
2526                 return PE_mouse_particles(C, location, extend, deselect, toggle);
2527         else if (obact && BKE_paint_select_face_test(obact))
2528                 retval = paintface_mouse_select(C, obact, location, extend, deselect, toggle);
2529         else if (BKE_paint_select_vert_test(obact))
2530                 retval = ed_wpaint_vertex_select_pick(C, location, extend, deselect, toggle, obact);
2531         else
2532                 retval = ed_object_select_pick(C, location, extend, deselect, toggle, center, enumerate, object);
2533
2534         /* passthrough allows tweaks
2535          * FINISHED to signal one operator worked
2536          * */
2537         if (retval)
2538                 return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED;
2539         else
2540                 return OPERATOR_PASS_THROUGH;  /* nothing selected, just passthrough */
2541 }
2542
2543 static int view3d_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
2544 {
2545         RNA_int_set_array(op->ptr, "location", event->mval);
2546
2547         return view3d_select_exec(C, op);
2548 }
2549
2550 void VIEW3D_OT_select(wmOperatorType *ot)
2551 {
2552         PropertyRNA *prop;
2553
2554         /* identifiers */
2555         ot->name = "Select";
2556         ot->description = "Select and activate item(s)";
2557         ot->idname = "VIEW3D_OT_select";
2558
2559         /* api callbacks */
2560         ot->invoke = view3d_select_invoke;
2561         ot->exec = view3d_select_exec;
2562         ot->poll = ED_operator_view3d_active;
2563
2564         /* flags */
2565         ot->flag = OPTYPE_UNDO;
2566
2567         /* properties */
2568         WM_operator_properties_mouse_select(ot);
2569
2570         RNA_def_boolean(ot->srna, "center", 0, "Center", "Use the object center when selecting, in editmode used to extend object selection");
2571         RNA_def_boolean(ot->srna, "enumerate", 0, "Enumerate", "List objects under the mouse (object mode only)");
2572         RNA_def_boolean(ot->srna, "object", 0, "Object", "Use object selection (editmode only)");
2573
2574         prop = RNA_def_int_vector(ot->srna, "location", 2, NULL, INT_MIN, INT_MAX, "Location", "Mouse location", INT_MIN, INT_MAX);
2575         RNA_def_property_flag(prop, PROP_HIDDEN);
2576 }
2577
2578
2579 /* -------------------- circle select --------------------------------------------- */
2580
2581 typedef struct CircleSelectUserData {
2582         ViewContext *vc;
2583         bool select;
2584         int   mval[2];
2585         float mval_fl[2];
2586         float radius;
2587         float radius_squared;
2588
2589         /* runtime */
2590         bool is_changed;
2591 } CircleSelectUserData;
2592
2593 static void view3d_userdata_circleselect_init(
2594         CircleSelectUserData *r_data,
2595         ViewContext *vc, const bool select, const int mval[2], const float rad)
2596 {
2597         r_data->vc = vc;
2598         r_data->select = select;
2599         copy_v2_v2_int(r_data->mval, mval);
2600         r_data->mval_fl[0] = mval[0];
2601         r_data->mval_fl[1] = mval[1];
2602
2603         r_data->radius = rad;
2604         r_data->radius_squared = rad * rad;
2605
2606         /* runtime */
2607         r_data->is_changed = false;
2608 }
2609
2610 static void mesh_circle_doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index))
2611 {
2612         CircleSelectUserData *data = userData;
2613
2614         if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
2615                 BM_vert_select_set(data->vc->em->bm, eve, data->select);
2616         }
2617 }
2618 static void mesh_circle_doSelectEdge(
2619         void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int UNUSED(index))
2620 {
2621         CircleSelectUserData *data = userData;
2622
2623         if (edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) {
2624                 BM_edge_select_set(data->vc->em->bm, eed, data->select);
2625         }
2626 }
2627 static void mesh_circle_doSelectFace(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
2628 {
2629         CircleSelectUserData *data = userData;
2630
2631         if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
2632                 BM_face_select_set(data->vc->em->bm, efa, data->select);
2633         }
2634 }
2635
2636 static void mesh_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
2637 {
2638         ToolSettings *ts = vc->scene->toolsettings;
2639         int bbsel;
2640         CircleSelectUserData data;
2641
2642         bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
2643         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
2644
2645         vc->em = BKE_editmesh_from_object(vc->obedit);
2646
2647         view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
2648
2649         if (ts->selectmode & SCE_SELECT_VERTEX) {
2650                 if (bbsel) {
2651                         edbm_backbuf_check_and_select_verts(vc->em, select);
2652                 }
2653                 else {
2654                         mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
2655                 }
2656         }
2657
2658         if (ts->selectmode & SCE_SELECT_EDGE) {
2659                 if (bbsel) {
2660                         edbm_backbuf_check_and_select_edges(vc->em, select);
2661                 }
2662                 else {
2663                         mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
2664                 }
2665         }
2666
2667         if (ts->selectmode & SCE_SELECT_FACE) {
2668                 if (bbsel) {
2669                         edbm_backbuf_check_and_select_faces(vc->em, select);
2670                 }
2671                 else {
2672                         mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
2673                 }
2674         }
2675
2676         EDBM_backbuf_free();
2677         EDBM_selectmode_flush(vc->em);
2678 }
2679
2680 static void paint_facesel_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
2681 {
2682         Object *ob = vc->obact;
2683         Mesh *me = ob->data;
2684         bool bbsel;
2685
2686         bm_vertoffs = me->totpoly + 1; /* max index array */
2687
2688         bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
2689         if (bbsel) {
2690                 edbm_backbuf_check_and_select_tfaces(me, select);
2691                 EDBM_backbuf_free();
2692                 paintface_flush_flags(ob, SELECT);
2693         }
2694 }
2695
2696 static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
2697 {
2698         CircleSelectUserData *data = userData;
2699
2700         if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
2701                 SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT);
2702         }
2703 }
2704 static void paint_vertsel_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
2705 {
2706         const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0;
2707         Object *ob = vc->obact;
2708         Mesh *me = ob->data;
2709         bool bbsel;
2710         /* CircleSelectUserData data = {NULL}; */ /* UNUSED */
2711
2712         if (use_zbuf) {
2713                 bm_vertoffs = me->totvert + 1; /* max index array */
2714
2715                 bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
2716                 if (bbsel) {
2717                         edbm_backbuf_check_and_select_verts_obmode(me, select);
2718                         EDBM_backbuf_free();
2719                 }
2720         }
2721         else {
2722                 CircleSelectUserData data;
2723
2724                 ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */
2725
2726                 view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
2727                 meshobject_foreachScreenVert(vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
2728         }
2729
2730         if (select == false) {
2731                 BKE_mesh_mselect_validate(me);
2732         }
2733         paintvert_flush_flags(ob);
2734 }
2735
2736
2737 static void nurbscurve_circle_doSelect(
2738         void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
2739 {
2740         CircleSelectUserData *data = userData;
2741         Object *obedit = data->vc->obedit;
2742         Curve *cu = (Curve *)obedit->data;
2743
2744         if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
2745                 if (bp) {
2746                         bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
2747                 }
2748                 else {
2749                         if (cu->drawflag & CU_HIDE_HANDLES) {
2750                                 /* can only be (beztindex == 0) here since handles are hidden */
2751                                 bezt->f1 = bezt->f2 = bezt->f3 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
2752                         }
2753                         else {
2754                                 if (beztindex == 0) {
2755                                         bezt->f1 = data->select ? (bezt->f1 | SELECT) : (bezt->f1 & ~SELECT);
2756                                 }
2757                                 else if (beztindex == 1) {
2758                                         bezt->f2 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
2759                                 }
2760                                 else {
2761                                         bezt->f3 = data->select ? (bezt->f3 | SELECT) : (bezt->f3 & ~SELECT);
2762                                 }
2763                         }
2764                 }
2765         }
2766 }
2767 static void nurbscurve_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
2768 {
2769         CircleSelectUserData data;
2770
2771         view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
2772
2773         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
2774         nurbs_foreachScreenVert(vc, nurbscurve_circle_doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
2775         BKE_curve_nurb_vert_active_validate(vc->obedit->data);
2776 }
2777
2778
2779 static void latticecurve_circle_doSelect(void *userData, BPoint *bp, const float screen_co[2])
2780 {
2781         CircleSelectUserData *data = userData;
2782
2783         if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
2784                 bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
2785         }
2786 }
2787 static void lattice_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
2788 {
2789         CircleSelectUserData data;
2790
2791         view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
2792
2793         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
2794         lattice_foreachScreenVert(vc, latticecurve_circle_doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
2795 }
2796
2797
2798 /* NOTE: pose-bone case is copied from editbone case... */
2799 static bool pchan_circle_doSelectJoint(void *userData, bPoseChannel *pchan, const float screen_co[2])
2800 {
2801         CircleSelectUserData *data = userData;
2802
2803         if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
2804                 if (data->select)
2805                         pchan->bone->flag |= BONE_SELECTED;
2806                 else
2807                         pchan->bone->flag &= ~BONE_SELECTED;
2808                 return 1;
2809         }
2810         return 0;
2811 }
2812 static void do_circle_select_pose__doSelectBone(
2813         void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2])
2814 {
2815         CircleSelectUserData *data = userData;
2816         bArmature *arm = data->vc->obact->data;
2817
2818         if (PBONE_SELECTABLE(arm, pchan->bone)) {
2819                 bool is_point_done = false;
2820                 int points_proj_tot = 0;
2821
2822                 /* project head location to screenspace */
2823                 if (screen_co_a[0] != IS_CLIPPED) {
2824                         points_proj_tot++;
2825                         if (pchan_circle_doSelectJoint(data, pchan, screen_co_a)) {
2826                                 is_point_done = true;
2827                         }
2828                 }
2829
2830                 /* project tail location to screenspace */
2831                 if (screen_co_b[0] != IS_CLIPPED) {
2832                         points_proj_tot++;
2833                         if (pchan_circle_doSelectJoint(data, pchan, screen_co_b)) {
2834                                 is_point_done = true;
2835                         }
2836                 }
2837
2838                 /* check if the head and/or tail is in the circle
2839                  * - the call to check also does the selection already
2840                  */
2841
2842                 /* only if the endpoints didn't get selected, deal with the middle of the bone too
2843                  * It works nicer to only do this if the head or tail are not in the circle,
2844                  * otherwise there is no way to circle select joints alone */
2845                 if ((is_point_done == false) && (points_proj_tot == 2) &&
2846                     edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b))
2847                 {
2848                         if (data->select) pchan->bone->flag |= BONE_SELECTED;
2849                         else              pchan->bone->flag &= ~BONE_SELECTED;
2850                         data->is_changed = true;
2851                 }
2852
2853                 data->is_changed |= is_point_done;
2854         }
2855 }
2856 static void pose_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
2857 {
2858         CircleSelectUserData data;
2859
2860         view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
2861
2862         ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */
2863
2864         pose_foreachScreenBone(vc, do_circle_select_pose__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
2865
2866         if (data.is_changed) {
2867                 bArmature *arm = vc->obact->data;
2868
2869                 WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obact);
2870
2871                 if (arm->flag & ARM_HAS_VIZ_DEPS) {
2872                         /* mask modifier ('armature' mode), etc. */
2873                         DEG_id_tag_update(&vc->obact->id, OB_RECALC_DATA);
2874                 }
2875
2876                 /* copy on write tag is needed (for the armature), or else no refresh happens */
2877                 DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
2878         }
2879 }
2880
2881 static bool armature_circle_doSelectJoint(void *userData, EditBone *ebone, const float screen_co[2], bool head)
2882 {
2883         CircleSelectUserData *data = userData;
2884
2885         if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
2886                 if (head) {
2887                         if (data->select)
2888                                 ebone->flag |= BONE_ROOTSEL;
2889                         else
2890                                 ebone->flag &= ~BONE_ROOTSEL;
2891                 }
2892                 else {
2893                         if (data->select)
2894                                 ebone->flag |= BONE_TIPSEL;
2895                         else
2896                                 ebone->flag &= ~BONE_TIPSEL;
2897                 }
2898                 return 1;
2899         }
2900         return 0;
2901 }
2902 static void do_circle_select_armature__doSelectBone(
2903         void *userData, struct EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2])
2904 {
2905         CircleSelectUserData *data = userData;
2906         bArmature *arm = data->vc->obedit->data;
2907
2908         if (data->select ? EBONE_SELECTABLE(arm, ebone) : EBONE_VISIBLE(arm, ebone)) {
2909                 bool is_point_done = false;
2910                 int points_proj_tot = 0;
2911
2912                 /* project head location to screenspace */
2913                 if (screen_co_a[0] != IS_CLIPPED) {
2914                         points_proj_tot++;
2915                         if (armature_circle_doSelectJoint(data, ebone, screen_co_a, true)) {
2916                                 is_point_done = true;
2917                         }
2918                 }
2919
2920                 /* project tail location to screenspace */
2921                 if (screen_co_b[0] != IS_CLIPPED) {
2922                         points_proj_tot++;
2923                         if (armature_circle_doSelectJoint(data, ebone, screen_co_b, false)) {
2924                                 is_point_done = true;
2925                         }
2926                 }
2927
2928                 /* check if the head and/or tail is in the circle
2929                  * - the call to check also does the selection already
2930                  */
2931
2932                 /* only if the endpoints didn't get selected, deal with the middle of the bone too
2933                  * It works nicer to only do this if the head or tail are not in the circle,
2934                  * otherwise there is no way to circle select joints alone */
2935                 if ((is_point_done == false) && (points_proj_tot == 2) &&
2936                     edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b))
2937                 {
2938                         if (data->select) ebone->flag |=  (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
2939                         else              ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
2940                         data->is_changed = true;
2941                 }
2942
2943                 data->is_changed |= is_point_done;
2944         }
2945 }
2946 static void armature_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
2947 {
2948         CircleSelectUserData data;
2949         bArmature *arm = vc->obedit->data;
2950
2951         view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
2952
2953         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
2954
2955         armature_foreachScreenBone(vc, do_circle_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
2956
2957         if (data.is_changed) {
2958                 ED_armature_edit_sync_selection(arm->edbo);
2959                 ED_armature_edit_validate_active(arm);
2960                 WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obedit);
2961         }
2962 }
2963
2964 static void do_circle_select_mball__doSelectElem(void *userData, struct MetaElem *ml, const float screen_co[2])
2965 {
2966         CircleSelectUserData *data = userData;
2967
2968         if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
2969                 if (data->select) ml->flag |=  SELECT;
2970                 else              ml->flag &= ~SELECT;
2971                 data->is_changed = true;
2972         }
2973 }
2974 static void mball_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
2975 {
2976         CircleSelectUserData data;
2977
2978         view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
2979
2980         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
2981
2982         mball_foreachScreenElem(vc, do_circle_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
2983 }
2984
2985 /** Callbacks for circle selection in Editmode */
2986
2987 static void obedit_circle_select(
2988         ViewContext *vc, const bool select, const int mval[2], float rad)
2989 {
2990         switch (vc->obedit->type) {
2991                 case OB_MESH:
2992                         mesh_circle_select(vc, select, mval, rad);
2993                         break;
2994                 case OB_CURVE:
2995                 case OB_SURF:
2996                         nurbscurve_circle_select(vc, select, mval, rad);
2997                         break;
2998                 case OB_LATTICE:
2999                         lattice_circle_select(vc, select, mval, rad);
3000                         break;