Internal refactoring of tracking module, should be no functional changes
[blender.git] / source / blender / editors / space_view3d / view3d_select.c
index c6a93a80b2e845e4dae2d5cbfedf107d57523b03..f9ebd4e39c1656fa0341634ca4aa4ed195ab08ff 100644 (file)
 #include "MEM_guardedalloc.h"
 
 #include "BLI_math.h"
-#include "BLI_blenlib.h"
+#include "BLI_lasso.h"
+#include "BLI_rect.h"
 #include "BLI_rand.h"
 #include "BLI_linklist.h"
+#include "BLI_listbase.h"
+#include "BLI_string.h"
 #include "BLI_utildefines.h"
 
 /* vertex box select */
@@ -61,6 +64,7 @@
 #include "BKE_context.h"
 #include "BKE_paint.h"
 #include "BKE_armature.h"
+#include "BKE_depsgraph.h"
 #include "BKE_tessmesh.h"
 #include "BKE_movieclip.h"
 #include "BKE_object.h"
@@ -319,79 +323,6 @@ static int edge_inside_rect(rcti *rect, short x1, short y1, short x2, short y2)
 #define MOVES_GESTURE 50
 #define MOVES_LASSO 500
 
-int lasso_inside(int mcords[][2], short moves, int sx, int sy)
-{
-       /* we do the angle rule, define that all added angles should be about zero or 2*PI */
-       float angletot = 0.0, len, dot, ang, cross, fp1[2], fp2[2];
-       int a;
-       int *p1, *p2;
-       
-       if (sx == IS_CLIPPED)
-               return 0;
-       
-       p1 = mcords[moves - 1];
-       p2 = mcords[0];
-       
-       /* first vector */
-       fp1[0] = (float)(p1[0] - sx);
-       fp1[1] = (float)(p1[1] - sy);
-       len = sqrt(fp1[0] * fp1[0] + fp1[1] * fp1[1]);
-       fp1[0] /= len;
-       fp1[1] /= len;
-       
-       for (a = 0; a < moves; a++) {
-               /* second vector */
-               fp2[0] = (float)(p2[0] - sx);
-               fp2[1] = (float)(p2[1] - sy);
-               len = sqrt(fp2[0] * fp2[0] + fp2[1] * fp2[1]);
-               fp2[0] /= len;
-               fp2[1] /= len;
-               
-               /* dot and angle and cross */
-               dot = fp1[0] * fp2[0] + fp1[1] * fp2[1];
-               ang = fabs(saacos(dot));
-
-               cross = (float)((p1[1] - p2[1]) * (p1[0] - sx) + (p2[0] - p1[0]) * (p1[1] - sy));
-               
-               if (cross < 0.0f) angletot -= ang;
-               else angletot += ang;
-               
-               /* circulate */
-               fp1[0] = fp2[0]; fp1[1] = fp2[1];
-               p1 = p2;
-               p2 = mcords[a + 1];
-       }
-       
-       if (fabs(angletot) > 4.0) return 1;
-       return 0;
-}
-
-/* edge version for lasso select. we assume boundbox check was done */
-int lasso_inside_edge(int mcords[][2], short moves, int x0, int y0, int x1, int y1)
-{
-       int v1[2], v2[2];
-       int a;
-
-       if (x0 == IS_CLIPPED || x1 == IS_CLIPPED)
-               return 0;
-       
-       v1[0] = x0, v1[1] = y0;
-       v2[0] = x1, v2[1] = y1;
-
-       /* check points in lasso */
-       if (lasso_inside(mcords, moves, v1[0], v1[1])) return 1;
-       if (lasso_inside(mcords, moves, v2[0], v2[1])) return 1;
-       
-       /* no points in lasso, so we have to intersect with lasso edge */
-       
-       if (isect_line_line_v2_int(mcords[0], mcords[moves - 1], v1, v2) > 0) return 1;
-       for (a = 0; a < moves - 1; a++) {
-               if (isect_line_line_v2_int(mcords[a], mcords[a + 1], v1, v2) > 0) return 1;
-       }
-       
-       return 0;
-}
-
 
 /* warning; lasso select with backbuffer-check draws in backbuf with persp(PERSP_WIN) 
  * and returns with persp(PERSP_VIEW). After lasso select backbuf is not OK
@@ -403,7 +334,7 @@ static void do_lasso_select_pose(ViewContext *vc, Object *ob, int mcords[][2], s
        int sco1[2], sco2[2];
        bArmature *arm = ob->data;
        
-       if (ob->type != OB_ARMATURE || ob->pose == NULL) return;
+       if ((ob->type != OB_ARMATURE) || (ob->pose == NULL)) return;
 
        for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
                if (PBONE_VISIBLE(arm, pchan->bone) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
@@ -412,12 +343,17 @@ static void do_lasso_select_pose(ViewContext *vc, Object *ob, int mcords[][2], s
                        mul_v3_m4v3(vec, ob->obmat, pchan->pose_tail);
                        project_int(vc->ar, vec, sco2);
                        
-                       if (lasso_inside_edge(mcords, moves, sco1[0], sco1[1], sco2[0], sco2[1])) {
+                       if (BLI_lasso_is_edge_inside(mcords, moves, sco1[0], sco1[1], sco2[0], sco2[1], IS_CLIPPED)) {
                                if (select) pchan->bone->flag |= BONE_SELECTED;
                                else pchan->bone->flag &= ~BONE_SELECTED;
                        }
                }
        }
+       
+       if (arm->flag & ARM_HAS_VIZ_DEPS) {
+               /* mask modifier ('armature' mode), etc. */
+               DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+       }
 }
 
 static void object_deselect_all_visible(Scene *scene, View3D *v3d)
@@ -441,7 +377,7 @@ static void do_lasso_select_objects(ViewContext *vc, int mcords[][2], short move
        for (base = vc->scene->base.first; base; base = base->next) {
                if (BASE_SELECTABLE(vc->v3d, base)) { /* use this to avoid un-needed lasso lookups */
                        project_short(vc->ar, base->object->obmat[3], &base->sx);
-                       if (lasso_inside(mcords, moves, base->sx, base->sy)) {
+                       if (BLI_lasso_is_point_inside(mcords, moves, base->sx, base->sy, IS_CLIPPED)) {
                                
                                if (select) ED_base_object_select(base, BA_SELECT);
                                else ED_base_object_select(base, BA_DESELECT);
@@ -454,26 +390,13 @@ static void do_lasso_select_objects(ViewContext *vc, int mcords[][2], short move
        }
 }
 
-static void lasso_select_boundbox(rcti *rect, int mcords[][2], short moves)
-{
-       short a;
-       
-       rect->xmin = rect->xmax = mcords[0][0];
-       rect->ymin = rect->ymax = mcords[0][1];
-       
-       for (a = 1; a < moves; a++) {
-               if (mcords[a][0] < rect->xmin) rect->xmin = mcords[a][0];
-               else if (mcords[a][0] > rect->xmax) rect->xmax = mcords[a][0];
-               if (mcords[a][1] < rect->ymin) rect->ymin = mcords[a][1];
-               else if (mcords[a][1] > rect->ymax) rect->ymax = mcords[a][1];
-       }
-}
-
 static void do_lasso_select_mesh__doSelectVert(void *userData, BMVert *eve, int x, int y, int UNUSED(index))
 {
        LassoSelectUserData *data = userData;
 
-       if (BLI_in_rcti(data->rect, x, y) && lasso_inside(data->mcords, data->moves, x, y)) {
+       if (BLI_in_rcti(data->rect, x, y) &&
+           BLI_lasso_is_point_inside(data->mcords, data->moves, x, y, IS_CLIPPED))
+       {
                BM_vert_select_set(data->vc->em->bm, eve, data->select);
        }
 }
@@ -484,14 +407,15 @@ static void do_lasso_select_mesh__doSelectEdge(void *userData, BMEdge *eed, int
        if (EDBM_backbuf_check(bm_solidoffs + index)) {
                if (data->pass == 0) {
                        if (edge_fully_inside_rect(data->rect, x0, y0, x1, y1)  &&
-                           lasso_inside(data->mcords, data->moves, x0, y0) &&
-                           lasso_inside(data->mcords, data->moves, x1, y1)) {
+                           BLI_lasso_is_point_inside(data->mcords, data->moves, x0, y0, IS_CLIPPED) &&
+                           BLI_lasso_is_point_inside(data->mcords, data->moves, x1, y1, IS_CLIPPED))
+                       {
                                BM_edge_select_set(data->vc->em->bm, eed, data->select);
-                               data->done = 1;
+                               data->done = TRUE;
                        }
                }
                else {
-                       if (lasso_inside_edge(data->mcords, data->moves, x0, y0, x1, y1)) {
+                       if (BLI_lasso_is_edge_inside(data->mcords, data->moves, x0, y0, x1, y1, IS_CLIPPED)) {
                                BM_edge_select_set(data->vc->em->bm, eed, data->select);
                        }
                }
@@ -501,7 +425,9 @@ static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, int
 {
        LassoSelectUserData *data = userData;
 
-       if (BLI_in_rcti(data->rect, x, y) && lasso_inside(data->mcords, data->moves, x, y)) {
+       if (BLI_in_rcti(data->rect, x, y) &&
+           BLI_lasso_is_point_inside(data->mcords, data->moves, x, y, IS_CLIPPED))
+       {
                BM_face_select_set(data->vc->em->bm, efa, data->select);
        }
 }
@@ -513,7 +439,7 @@ static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves,
        rcti rect;
        int bbsel;
        
-       lasso_select_boundbox(&rect, mcords, moves);
+       BLI_lasso_boundbox(&rect, mcords, moves);
        
        /* set editmesh */
        vc->em = BMEdit_FromObject(vc->obedit);
@@ -523,7 +449,7 @@ static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves,
        data.mcords = mcords;
        data.moves = moves;
        data.select = select;
-       data.done = 0;
+       data.done = FALSE;
        data.pass = 0;
 
        if (extend == 0 && select)
@@ -567,80 +493,20 @@ static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves,
        EDBM_selectmode_flush(vc->em);
 }
 
-/* BMESH_TODO */
-#if 0
-/* this is an exception in that its the only lasso that dosnt use the 3d view (uses space image view) */
-static void do_lasso_select_mesh_uv(int mcords[][2], short moves, short select)
-{
-       EditFace *efa;
-       MTFace *tf;
-       int screenUV[2], nverts, i, ok = 1;
-       rcti rect;
-       
-       lasso_select_boundbox(&rect, mcords, moves);
-       
-       if (draw_uvs_face_check()) { /* Face Center Sel */
-               float cent[2];
-               ok = 0;
-               for (efa = em->faces.first; efa; efa = efa->next) {
-                       /* assume not touched */
-                       efa->tmp.l = 0;
-                       tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-                       if ((select) != (simaFaceSel_Check(efa, tf))) {
-                               uv_center(tf->uv, cent, (void *)efa->v4);
-                               uvco_to_areaco_noclip(cent, screenUV);
-                               if (BLI_in_rcti(&rect, screenUV[0], screenUV[1]) && lasso_inside(mcords, moves, screenUV[0], screenUV[1])) {
-                                       efa->tmp.l = ok = 1;
-                               }
-                       }
-               }
-               /* (de)selects all tagged faces and deals with sticky modes */
-               if (ok)
-                       uvface_setsel__internal(select);
-               
-       }
-       else { /* Vert Sel*/
-               for (efa = em->faces.first; efa; efa = efa->next) {
-                       tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-                       if (uvedit_face_visible(scene, ima, efa, tf)) {         
-                               nverts = efa->v4 ? 4 : 3;
-                               for (i = 0; i < nverts; i++) {
-                                       if ((select) != (simaUVSel_Check(efa, tf, i))) {
-                                               uvco_to_areaco_noclip(tf->uv[i], screenUV);
-                                               if (BLI_in_rcti(&rect, screenUV[0], screenUV[1]) && lasso_inside(mcords, moves, screenUV[0], screenUV[1])) {
-                                                       if (select) {
-                                                               simaUVSel_Set(efa, tf, i);
-                                                       }
-                                                       else {
-                                                               simaUVSel_UnSet(efa, tf, i);
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-       if (ok && G.sima->flag & SI_SYNC_UVSEL) {
-               if (select) EM_select_flush(vc->em);
-               else EM_deselect_flush(vc->em);
-       }
-}
-#endif
-
 static void do_lasso_select_curve__doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, int x, int y)
 {
        LassoSelectUserData *data = userData;
        Object *obedit = data->vc->obedit;
        Curve *cu = (Curve *)obedit->data;
 
-       if (lasso_inside(data->mcords, data->moves, x, y)) {
+       if (BLI_lasso_is_point_inside(data->mcords, data->moves, x, y, IS_CLIPPED)) {
                if (bp) {
                        bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
                        if (bp == cu->lastsel && !(bp->f1 & 1)) cu->lastsel = NULL;
                }
                else {
                        if (cu->drawflag & CU_HIDE_HANDLES) {
-                               /* can only be beztindex==0 here since handles are hidden */
+                               /* can only be (beztindex == 0) here since handles are hidden */
                                bezt->f1 = bezt->f2 = bezt->f3 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
                        }
                        else {
@@ -681,7 +547,7 @@ static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, int x,
 {
        LassoSelectUserData *data = userData;
 
-       if (lasso_inside(data->mcords, data->moves, x, y)) {
+       if (BLI_lasso_is_point_inside(data->mcords, data->moves, x, y, IS_CLIPPED)) {
                bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
        }
 }
@@ -722,20 +588,22 @@ static void do_lasso_select_armature(ViewContext *vc, int mcords[][2], short mov
                        project_short(vc->ar, vec, sco2);
                        
                        didpoint = 0;
-                       if (lasso_inside(mcords, moves, sco1[0], sco1[1])) {
+                       if (BLI_lasso_is_point_inside(mcords, moves, sco1[0], sco1[1], IS_CLIPPED)) {
                                if (select) ebone->flag |= BONE_ROOTSEL;
                                else ebone->flag &= ~BONE_ROOTSEL;
                                didpoint = 1;
                                change = TRUE;
                        }
-                       if (lasso_inside(mcords, moves, sco2[0], sco2[1])) {
+                       if (BLI_lasso_is_point_inside(mcords, moves, sco2[0], sco2[1], IS_CLIPPED)) {
                                if (select) ebone->flag |= BONE_TIPSEL;
                                else ebone->flag &= ~BONE_TIPSEL;
                                didpoint = 1;
                                change = TRUE;
                        }
                        /* if one of points selected, we skip the bone itself */
-                       if (didpoint == 0 && lasso_inside_edge(mcords, moves, sco1[0], sco1[1], sco2[0], sco2[1])) {
+                       if (didpoint == 0 &&
+                           BLI_lasso_is_edge_inside(mcords, moves, sco1[0], sco1[1], sco2[0], sco2[1], IS_CLIPPED))
+                       {
                                if (select) ebone->flag |= BONE_TIPSEL | BONE_ROOTSEL | BONE_SELECTED;
                                else ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
                                change = TRUE;
@@ -771,7 +639,7 @@ static void do_lasso_select_meta(ViewContext *vc, int mcords[][2], short moves,
                mul_v3_m4v3(vec, vc->obedit->obmat, &ml->x);
                project_short(vc->ar, vec, sco);
 
-               if (lasso_inside(mcords, moves, sco[0], sco[1])) {
+               if (BLI_lasso_is_point_inside(mcords, moves, sco[0], sco[1], IS_CLIPPED)) {
                        if (select) ml->flag |= SELECT;
                        else ml->flag &= ~SELECT;
                }
@@ -850,7 +718,7 @@ static void do_lasso_select_paintvert(ViewContext *vc, int mcords[][2], short mo
                paintvert_deselect_all_visible(ob, SEL_DESELECT, FALSE);  /* flush selection at the end */
        bm_vertoffs = me->totvert + 1; /* max index array */
 
-       lasso_select_boundbox(&rect, mcords, moves);
+       BLI_lasso_boundbox(&rect, mcords, moves);
        EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
 
        edbm_backbuf_check_and_select_verts_obmode(me, select);
@@ -873,7 +741,7 @@ static void do_lasso_select_paintface(ViewContext *vc, int mcords[][2], short mo
 
        bm_vertoffs = me->totpoly + 1; /* max index array */
 
-       lasso_select_boundbox(&rect, mcords, moves);
+       BLI_lasso_boundbox(&rect, mcords, moves);
        EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
        
        edbm_backbuf_check_and_select_tfaces(me, select);
@@ -893,7 +761,7 @@ static void do_lasso_select_node(int mcords[][2], short moves, short select)
        short node_cent[2];
        float node_centf[2];
        
-       lasso_select_boundbox(&rect, mcords, moves);
+       BLI_lasso_boundbox(&rect, mcords, moves);
        
        /* store selection in temp test flag */
        for (node = snode->edittree->nodes.first; node; node = node->next) {
@@ -902,7 +770,7 @@ static void do_lasso_select_node(int mcords[][2], short moves, short select)
                node_centf[1] = (node->totr.ymin + node->totr.ymax) / 2;
                
                ipoco_to_areaco_noclip(G.v2d, node_centf, node_cent);
-               if (BLI_in_rcti(&rect, node_cent[0], node_cent[1]) && lasso_inside(mcords, moves, node_cent[0], node_cent[1])) {
+               if (BLI_in_rcti(&rect, node_cent[0], node_cent[1]) && BLI_lasso_is_point_inside(mcords, moves, node_cent[0], node_cent[1])) {
                        if (select) {
                                node->flag |= SELECT;
                        }
@@ -965,21 +833,10 @@ static void view3d_lasso_select(bContext *C, ViewContext *vc, int mcords[][2], s
 static int view3d_lasso_select_exec(bContext *C, wmOperator *op)
 {
        ViewContext vc;
-       int i = 0;
-       int mcords[1024][2];
-
-       RNA_BEGIN(op->ptr, itemptr, "path") {
-               float loc[2];
-               
-               RNA_float_get_array(&itemptr, "loc", loc);
-               mcords[i][0] = (int)loc[0];
-               mcords[i][1] = (int)loc[1];
-               i++;
-               if (i >= 1024) break;
-       }
-       RNA_END;
+       int mcords_tot;
+       int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
        
-       if (i > 1) {
+       if (mcords) {
                short extend, select;
                view3d_operator_needs_opengl(C);
                
@@ -988,8 +845,10 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op)
                
                extend = RNA_boolean_get(op->ptr, "extend");
                select = !RNA_boolean_get(op->ptr, "deselect");
-               view3d_lasso_select(C, &vc, mcords, i, extend, select);
+               view3d_lasso_select(C, &vc, mcords, mcords_tot, extend, select);
                
+               MEM_freeN(mcords);
+
                return OPERATOR_FINISHED;
        }
        return OPERATOR_PASS_THROUGH;
@@ -1113,7 +972,8 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
        const char *name = object_mouse_select_menu_data[name_index].idname;
 
        if (!extend) {
-               CTX_DATA_BEGIN(C, Base *, base, selectable_bases) {
+               CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
+               {
                        if (base->flag & SELECT) {
                                ED_base_object_select(base, BA_DESELECT);
                                changed = 1;
@@ -1122,7 +982,8 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
                CTX_DATA_END;
        }
 
-       CTX_DATA_BEGIN(C, Base *, base, selectable_bases) {
+       CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
+       {
                /* this is a bit dodjy, there should only be ONE object with this name, but library objects can mess this up */
                if (strcmp(name, base->object->id.name + 2) == 0) {
                        ED_base_object_activate(C, base);
@@ -1189,7 +1050,8 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int
        short ok;
        LinkNode *linklist = NULL;
        
-       CTX_DATA_BEGIN(C, Base *, base, selectable_bases) {
+       CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
+       {
                ok = FALSE;
 
                /* two selection methods, the CTRL select uses max dist of 15 */
@@ -1324,19 +1186,19 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int
        View3D *v3d = vc->v3d;
        Base *base, *basact = NULL;
        static int lastmval[2] = {-100, -100};
-       int a, donearest = 0;
+       int a, do_nearest = FALSE;
        
        /* define if we use solid nearest select or not */
        if (v3d->drawtype > OB_WIRE) {
-               donearest = 1;
+               do_nearest = TRUE;
                if (ABS(mval[0] - lastmval[0]) < 3 && ABS(mval[1] - lastmval[1]) < 3) {
                        if (!has_bones) /* hrms, if theres bones we always do nearest */
-                               donearest = 0;
+                               do_nearest = FALSE;
                }
        }
        lastmval[0] = mval[0]; lastmval[1] = mval[1];
        
-       if (donearest) {
+       if (do_nearest) {
                unsigned int min = 0xFFFFFFFF;
                int selcol = 0, notcol = 0;
                
@@ -1441,11 +1303,11 @@ static void deselect_all_tracks(MovieTracking *tracking)
 
        object = tracking->objects.first;
        while (object) {
-               ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object);
+               ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
                MovieTrackingTrack *track = tracksbase->first;
 
                while (track) {
-                       BKE_tracking_deselect_track(track, TRACK_AREA_ALL);
+                       BKE_tracking_track_deselect(track, TRACK_AREA_ALL);
 
                        track = track->next;
                }
@@ -1455,7 +1317,7 @@ static void deselect_all_tracks(MovieTracking *tracking)
 }
 
 /* mval is region coords */
-static int mouse_select(bContext *C, const int mval[2], short extend, short obcenter, short enumerate)
+static int mouse_select(bContext *C, const int mval[2], short extend, short deselect, short toggle, short obcenter, short enumerate)
 {
        ViewContext vc;
        ARegion *ar = CTX_wm_region(C);
@@ -1541,23 +1403,23 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short obce
                                                        /* index of bundle is 1<<16-based. if there's no "bone" index
                                                         * in hight word, this buffer value belongs to camera,. not to bundle */
                                                        if (buffer[4 * i + 3] & 0xFFFF0000) {
-                                                               MovieClip *clip = object_get_movieclip(scene, basact->object, 0);
+                                                               MovieClip *clip = BKE_object_movieclip_get(scene, basact->object, 0);
                                                                MovieTracking *tracking = &clip->tracking;
                                                                ListBase *tracksbase;
                                                                MovieTrackingTrack *track;
 
-                                                               track = BKE_tracking_indexed_track(&clip->tracking, hitresult >> 16, &tracksbase);
+                                                               track = BKE_tracking_track_get_indexed(&clip->tracking, hitresult >> 16, &tracksbase);
 
                                                                if (TRACK_SELECTED(track) && extend) {
                                                                        changed = 0;
-                                                                       BKE_tracking_deselect_track(track, TRACK_AREA_ALL);
+                                                                       BKE_tracking_track_deselect(track, TRACK_AREA_ALL);
                                                                }
                                                                else {
                                                                        int oldsel = TRACK_SELECTED(track) ? 1 : 0;
                                                                        if (!extend)
                                                                                deselect_all_tracks(tracking);
 
-                                                                       BKE_tracking_select_track(tracksbase, track, TRACK_AREA_ALL, extend);
+                                                                       BKE_tracking_track_select(tracksbase, track, TRACK_AREA_ALL, extend);
 
                                                                        if (oldsel != (TRACK_SELECTED(track) ? 1 : 0))
                                                                                changed = 1;
@@ -1582,7 +1444,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short obce
                                                }
                                        }
                                }
-                               else if (ED_do_pose_selectbuffer(scene, basact, buffer, hits, extend) ) {   /* then bone is found */
+                               else if (ED_do_pose_selectbuffer(scene, basact, buffer, hits, extend, deselect, toggle) ) {   /* then bone is found */
                                
                                        /* we make the armature selected: 
                                         * not-selected active object in posemode won't work well for tools */
@@ -1621,19 +1483,25 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short obce
 
                        oldbasact = BASACT;
                        
-                       if (!extend) {
-                               deselectall_except(scene, basact);
+                       if (extend) {
                                ED_base_object_select(basact, BA_SELECT);
                        }
-                       else if (0) {
-                               // XXX select_all_from_groups(basact);
+                       else if (deselect) {
+                               ED_base_object_select(basact, BA_DESELECT);
                        }
-                       else {
+                       else if (toggle) {
                                if (basact->flag & SELECT) {
-                                       if (basact == oldbasact)
+                                       if (basact == oldbasact) {
                                                ED_base_object_select(basact, BA_DESELECT);
+                                       }
                                }
-                               else ED_base_object_select(basact, BA_SELECT);
+                               else {
+                                       ED_base_object_select(basact, BA_SELECT);
+                               }
+                       }
+                       else {
+                               deselectall_except(scene, basact);
+                               ED_base_object_select(basact, BA_SELECT);
                        }
 
                        if (oldbasact != basact) {
@@ -1690,7 +1558,7 @@ static void do_nurbs_box_select__doSelect(void *userData, Nurb *UNUSED(nu), BPoi
                }
                else {
                        if (cu->drawflag & CU_HIDE_HANDLES) {
-                               /* can only be beztindex==0 here since handles are hidden */
+                               /* can only be (beztindex == 0) here since handles are hidden */
                                bezt->f1 = bezt->f2 = bezt->f3 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
                        }
                        else {
@@ -1767,7 +1635,7 @@ static void do_mesh_box_select__doSelectEdge(void *userData, BMEdge *eed, int x0
                if (data->pass == 0) {
                        if (edge_fully_inside_rect(data->rect, x0, y0, x1, y1)) {
                                BM_edge_select_set(data->vc->em->bm, eed, data->select);
-                               data->done = 1;
+                               data->done = TRUE;
                        }
                }
                else {
@@ -1795,7 +1663,7 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int exten
        data.rect = rect;
        data.select = select;
        data.pass = 0;
-       data.done = 0;
+       data.done = FALSE;
 
        if (extend == 0 && select)
                EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT);
@@ -1967,7 +1835,8 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, i
        
        if (extend == 0 && select) {
                if (bone_only) {
-                       CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) {
+                       CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
+                       {
                                if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
                                        pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
                                }
@@ -2001,7 +1870,6 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, i
                for (base = vc->scene->base.first; base && hits; base = base->next) {
                        if (BASE_SELECTABLE(vc->v3d, base)) {
                                while (base->selcol == (*col & 0xFFFF)) {   /* we got an object */
-                                       
                                        if (*col & 0xFFFF0000) {                    /* we got a bone */
                                                bone = get_indexed_bone(base->object, *col & ~(BONESEL_ANY));
                                                if (bone) {
@@ -2009,16 +1877,13 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, i
                                                                if ((bone->flag & BONE_UNSELECTABLE) == 0) {
                                                                        bone->flag |= BONE_SELECTED;
                                                                        bone_selected = 1;
-// XXX                                                                 select_actionchannel_by_name(base->object->action, bone->name, 1);
                                                                }
                                                        }
                                                        else {
                                                                bArmature *arm = base->object->data;
                                                                bone->flag &= ~BONE_SELECTED;
-// XXX                                                                 select_actionchannel_by_name(base->object->action, bone->name, 0);
                                                                if (arm->act_bone == bone)
                                                                        arm->act_bone = NULL;
-                                                               
                                                        }
                                                }
                                        }
@@ -2028,7 +1893,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, i
                                                else
                                                        ED_base_object_select(base, BA_DESELECT);
                                        }
-
+                                       
                                        col += 4; /* next color */
                                        hits--;
                                        if (hits == 0) break;
@@ -2036,12 +1901,22 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, i
                        }
                        
                        if (bone_selected) {
-                               WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, base->object);
+                               Object *ob = base->object;
+                               
+                               if (ob && (ob->type == OB_ARMATURE)) {
+                                       bArmature *arm = ob->data;
+                                       
+                                       WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+                                       
+                                       if (arm && (arm->flag & ARM_HAS_VIZ_DEPS)) {
+                                               /* mask modifier ('armature' mode), etc. */
+                                               DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+                                       }
+                               }
                        }
                }
-
+               
                WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
-
        }
        MEM_freeN(vbuffer);
 
@@ -2186,15 +2061,21 @@ static int vertsel_vert_pick(struct bContext *C, Mesh *me, const int mval[2], un
 
 /* mouse selection in weight paint */
 /* gets called via generic mouse select operator */
-static int mouse_weight_paint_vertex_select(bContext *C, const int mval[2], short extend, Object *obact)
+static int mouse_weight_paint_vertex_select(bContext *C, const int mval[2], short extend, short deselect, short toggle, Object *obact)
 {
-       Mesh*me = obact->data; /* already checked for NULL */
+       Mesh *me = obact->data; /* already checked for NULL */
        unsigned int index = 0;
        MVert *mv;
 
        if (vertsel_vert_pick(C, me, mval, &index, 50)) {
                mv = me->mvert + index;
                if (extend) {
+                       mv->flag |= SELECT;
+               }
+               else if (deselect) {
+                       mv->flag &= ~SELECT;
+               }
+               else if (toggle) {
                        mv->flag ^= SELECT;
                }
                else {
@@ -2216,6 +2097,8 @@ static int view3d_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
        Object *obedit = CTX_data_edit_object(C);
        Object *obact = CTX_data_active_object(C);
        short extend = RNA_boolean_get(op->ptr, "extend");
+       short deselect = RNA_boolean_get(op->ptr, "deselect");
+       short toggle = RNA_boolean_get(op->ptr, "toggle");
        short center = RNA_boolean_get(op->ptr, "center");
        short enumerate = RNA_boolean_get(op->ptr, "enumerate");
        short object = RNA_boolean_get(op->ptr, "object");
@@ -2235,27 +2118,27 @@ static int view3d_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
 
        if (obedit && object == FALSE) {
                if (obedit->type == OB_MESH)
-                       retval = mouse_mesh(C, event->mval, extend);
+                       retval = mouse_mesh(C, event->mval, extend, deselect, toggle);
                else if (obedit->type == OB_ARMATURE)
-                       retval = mouse_armature(C, event->mval, extend);
+                       retval = mouse_armature(C, event->mval, extend, deselect, toggle);
                else if (obedit->type == OB_LATTICE)
-                       retval = mouse_lattice(C, event->mval, extend);
+                       retval = mouse_lattice(C, event->mval, extend, deselect, toggle);
                else if (ELEM(obedit->type, OB_CURVE, OB_SURF))
-                       retval = mouse_nurb(C, event->mval, extend);
+                       retval = mouse_nurb(C, event->mval, extend, deselect, toggle);
                else if (obedit->type == OB_MBALL)
-                       retval = mouse_mball(C, event->mval, extend);
+                       retval = mouse_mball(C, event->mval, extend, deselect, toggle);
                        
        }
        else if (obact && obact->mode & OB_MODE_SCULPT)
                return OPERATOR_CANCELLED;
        else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT)
-               return PE_mouse_particles(C, event->mval, extend);
+               return PE_mouse_particles(C, event->mval, extend, deselect, toggle);
        else if (obact && paint_facesel_test(obact))
-               retval = paintface_mouse_select(C, obact, event->mval, extend);
+               retval = paintface_mouse_select(C, obact, event->mval, extend, deselect, toggle);
        else if (paint_vertsel_test(obact))
-               retval = mouse_weight_paint_vertex_select(C, event->mval, extend, obact);
+               retval = mouse_weight_paint_vertex_select(C, event->mval, extend, deselect, toggle, obact);
        else
-               retval = mouse_select(C, event->mval, extend, center, enumerate);
+               retval = mouse_select(C, event->mval, extend, deselect, toggle, center, enumerate);
 
        /* passthrough allows tweaks
         * FINISHED to signal one operator worked
@@ -2281,7 +2164,8 @@ void VIEW3D_OT_select(wmOperatorType *ot)
        ot->flag = OPTYPE_UNDO;
        
        /* properties */
-       RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first");
+       WM_operator_properties_mouse_select(ot);
+
        RNA_def_boolean(ot->srna, "center", 0, "Center", "Use the object center when selecting, in editmode used to extend object selection");
        RNA_def_boolean(ot->srna, "enumerate", 0, "Enumerate", "List objects under the mouse (object mode only)");
        RNA_def_boolean(ot->srna, "object", 0, "Object", "Use object selection (editmode only)");
@@ -2332,7 +2216,7 @@ static void mesh_circle_select(ViewContext *vc, int select, const int mval[2], f
        int bbsel;
        CircleSelectUserData data;
        
-       bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0));
+       bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
        ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
 
        vc->em = BMEdit_FromObject(vc->obedit);
@@ -2383,7 +2267,7 @@ static void paint_facesel_circle_select(ViewContext *vc, int select, const int m
        if (me) {
                bm_vertoffs = me->totpoly + 1; /* max index array */
 
-               /* bbsel= */ /* UNUSED */ EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0));
+               /* bbsel= */ /* UNUSED */ EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
                edbm_backbuf_check_and_select_tfaces(me, select == LEFTMOUSE);
                EDBM_backbuf_free();
        }
@@ -2424,7 +2308,7 @@ static void nurbscurve_circle_doSelect(void *userData, Nurb *UNUSED(nu), BPoint
                }
                else {
                        if (cu->drawflag & CU_HIDE_HANDLES) {
-                               /* can only be beztindex==0 here since handles are hidden */
+                               /* can only be (beztindex == 0) here since handles are hidden */
                                bezt->f1 = bezt->f2 = bezt->f3 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
                        }
                        else {