Index: source/blender/editors/include/ED_armature.h =================================================================== --- source/blender/editors/include/ED_armature.h (revision 46963) +++ source/blender/editors/include/ED_armature.h (working copy) @@ -113,8 +113,8 @@ void ED_armature_deselect_all_visible(struct Object *obedit); int ED_do_pose_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer, - short hits, short extend); -int mouse_armature(struct bContext *C, const int mval[2], int extend); + short hits, short extend, short deselect, short toggle); +int mouse_armature(struct bContext *C, const int mval[2], int extend, int deselect, int toggle); int join_armature_exec(struct bContext *C, struct wmOperator *op); struct Bone *get_indexed_bone(struct Object *ob, int index); float ED_rollBoneToVector(EditBone *bone, const float new_up_axis[3], const short axis_only); Index: source/blender/editors/include/ED_mesh.h =================================================================== --- source/blender/editors/include/ED_mesh.h (revision 46963) +++ source/blender/editors/include/ED_mesh.h (working copy) @@ -156,7 +156,7 @@ /* editmesh_mods.c */ extern unsigned int bm_vertoffs, bm_solidoffs, bm_wireoffs; -int mouse_mesh(struct bContext *C, const int mval[2], short extend); +int mouse_mesh(struct bContext *C, const int mval[2], short extend, short deselect, short toggle); struct BMVert *editbmesh_get_x_mirror_vert(struct Object *ob, struct BMEditMesh *em, struct BMVert *eve, const float co[3], int index); int mesh_get_x_mirror_vert(struct Object *ob, int index); @@ -184,7 +184,7 @@ /* editface.c */ void paintface_flush_flags(struct Object *ob); -int paintface_mouse_select(struct bContext *C, struct Object *ob, const int mval[2], int extend); +int paintface_mouse_select(struct bContext *C, struct Object *ob, const int mval[2], int extend, int deselect, int toggle); int do_paintface_box_select(struct ViewContext *vc, struct rcti *rect, int select, int extend); void paintface_deselect_all_visible(struct Object *ob, int action, short flush_flags); void paintface_select_linked(struct bContext *C, struct Object *ob, int mval[2], int mode); Index: source/blender/editors/include/ED_object.h =================================================================== --- source/blender/editors/include/ED_object.h (revision 46963) +++ source/blender/editors/include/ED_object.h (working copy) @@ -152,7 +152,7 @@ void ED_object_constraint_dependency_update(struct Main *bmain, struct Scene *scene, struct Object *ob); /* object_lattice.c */ -int mouse_lattice(struct bContext *C, const int mval[2], int extend); +int mouse_lattice(struct bContext *C, const int mval[2], int extend, int deselect, int toggle); void undo_push_lattice(struct bContext *C, const char *name); /* object_lattice.c */ Index: source/blender/editors/include/ED_curve.h =================================================================== --- source/blender/editors/include/ED_curve.h (revision 46963) +++ source/blender/editors/include/ED_curve.h (working copy) @@ -65,7 +65,7 @@ void BKE_curve_editNurb_free(struct Curve *cu); -int mouse_nurb(struct bContext *C, const int mval[2], int extend); +int mouse_nurb(struct bContext *C, const int mval[2], int extend, int deselect, int toggle); struct Nurb *add_nurbs_primitive(struct bContext *C, float mat[4][4], int type, int newob); Index: source/blender/editors/include/ED_mball.h =================================================================== --- source/blender/editors/include/ED_mball.h (revision 46963) +++ source/blender/editors/include/ED_mball.h (working copy) @@ -40,7 +40,7 @@ struct MetaElem *add_metaball_primitive(struct bContext *C, float mat[4][4], int type, int newname); -int mouse_mball(struct bContext *C, const int mval[2], int extend); +int mouse_mball(struct bContext *C, const int mval[2], int extend, int deselect, int toggle); void free_editMball(struct Object *obedit); void make_editMball(struct Object *obedit); Index: source/blender/editors/space_view3d/view3d_select.c =================================================================== --- source/blender/editors/space_view3d/view3d_select.c (revision 46963) +++ source/blender/editors/space_view3d/view3d_select.c (working copy) @@ -1311,7 +1311,7 @@ } /* 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); @@ -1438,7 +1438,7 @@ } } } - 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 */ @@ -1477,20 +1477,23 @@ 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) ED_base_object_select(basact, BA_DESELECT); } else ED_base_object_select(basact, BA_SELECT); } + else { + deselectall_except(scene, basact); + ED_base_object_select(basact, BA_SELECT); + } if (oldbasact != basact) { ED_base_object_activate(C, basact); /* adds notifier */ @@ -2043,7 +2046,7 @@ /* 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 */ unsigned int index = 0; @@ -2052,6 +2055,12 @@ 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 { @@ -2073,6 +2082,8 @@ 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"); @@ -2092,27 +2103,27 @@ 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 | 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 @@ -2139,6 +2150,8 @@ /* properties */ RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first"); + RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from selection"); + RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Selection", "Toggles selection"); 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)"); Index: source/blender/editors/space_view3d/view3d_ops.c =================================================================== --- source/blender/editors/space_view3d/view3d_ops.c (revision 46963) +++ source/blender/editors/space_view3d/view3d_ops.c (working copy) @@ -272,21 +272,29 @@ /* selection*/ kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, 0, 0); RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", FALSE); RNA_boolean_set(kmi->ptr, "center", FALSE); RNA_boolean_set(kmi->ptr, "object", FALSE); RNA_boolean_set(kmi->ptr, "enumerate", FALSE); kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0); - RNA_boolean_set(kmi->ptr, "extend", TRUE); + RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", TRUE); RNA_boolean_set(kmi->ptr, "center", FALSE); RNA_boolean_set(kmi->ptr, "object", FALSE); RNA_boolean_set(kmi->ptr, "enumerate", FALSE); kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", FALSE); RNA_boolean_set(kmi->ptr, "center", TRUE); RNA_boolean_set(kmi->ptr, "object", TRUE); /* use Ctrl+Select for 2 purposes */ RNA_boolean_set(kmi->ptr, "enumerate", FALSE); kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0); RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", FALSE); RNA_boolean_set(kmi->ptr, "center", FALSE); RNA_boolean_set(kmi->ptr, "object", FALSE); RNA_boolean_set(kmi->ptr, "enumerate", TRUE); @@ -294,21 +302,29 @@ /* selection key-combinations */ kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT | KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "extend", TRUE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", TRUE); RNA_boolean_set(kmi->ptr, "center", TRUE); RNA_boolean_set(kmi->ptr, "object", FALSE); RNA_boolean_set(kmi->ptr, "enumerate", FALSE); kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, KM_CTRL | KM_ALT, 0); RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", FALSE); RNA_boolean_set(kmi->ptr, "center", TRUE); RNA_boolean_set(kmi->ptr, "object", FALSE); RNA_boolean_set(kmi->ptr, "enumerate", TRUE); kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT | KM_ALT, 0); - RNA_boolean_set(kmi->ptr, "extend", TRUE); + RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", TRUE); RNA_boolean_set(kmi->ptr, "center", FALSE); RNA_boolean_set(kmi->ptr, "object", FALSE); RNA_boolean_set(kmi->ptr, "enumerate", TRUE); kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT | KM_CTRL | KM_ALT, 0); - RNA_boolean_set(kmi->ptr, "extend", TRUE); + RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", TRUE); RNA_boolean_set(kmi->ptr, "center", TRUE); RNA_boolean_set(kmi->ptr, "object", FALSE); RNA_boolean_set(kmi->ptr, "enumerate", TRUE); Index: source/blender/editors/armature/editarmature.c =================================================================== --- source/blender/editors/armature/editarmature.c (revision 46963) +++ source/blender/editors/armature/editarmature.c (working copy) @@ -1842,7 +1842,7 @@ } /* context: editmode armature in view3d */ -int mouse_armature(bContext *C, const int mval[2], int extend) +int mouse_armature(bContext *C, const int mval[2], int extend, int deselect, int toggle) { Object *obedit = CTX_data_edit_object(C); bArmature *arm = obedit->data; @@ -1857,7 +1857,7 @@ nearBone = get_nearest_editbonepoint(&vc, mval, arm->edbo, 1, &selmask); if (nearBone) { - if (!extend) + if (!extend && !deselect && !toggle) ED_armature_deselect_all(obedit, 0); /* by definition the non-root connected bones have no root point drawn, @@ -1867,6 +1867,18 @@ if (nearBone->parent && (nearBone->flag & BONE_CONNECTED)) { /* click in a chain */ if (extend) { + /* select this bone */ + nearBone->flag |= BONE_TIPSEL; + nearBone->parent->flag |= BONE_TIPSEL; + } + else if (deselect) { + /* deselect this bone */ + nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED); + /* only deselect parent tip if it is not selected */ + if (!(nearBone->parent->flag & BONE_SELECTED)) + nearBone->parent->flag &= ~BONE_TIPSEL; + } + else if (toggle) { /* hold shift inverts this bone's selection */ if (nearBone->flag & BONE_SELECTED) { /* deselect this bone */ @@ -1889,18 +1901,29 @@ } else { if (extend) { + nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL); + } + else if (deselect) { + nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL); + } + else if (toggle) { /* hold shift inverts this bone's selection */ if (nearBone->flag & BONE_SELECTED) nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL); else nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL); } - else nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL); + else + nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL); } } else { - if (extend && (nearBone->flag & selmask)) + if (extend) + nearBone->flag |= selmask; + else if (deselect) nearBone->flag &= ~selmask; + else if (toggle && (nearBone->flag & selmask)) + nearBone->flag &= ~selmask; else nearBone->flag |= selmask; } @@ -4475,7 +4498,7 @@ /* called from editview.c, for mode-less pose selection */ /* assumes scene obact and basact is still on old situation */ -int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, short extend) +int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, short extend, short deselect, short toggle) { Object *ob = base->object; Bone *nearBone; @@ -4494,7 +4517,7 @@ * note, special exception for armature mode so we can do multi-select * we could check for multi-select explicitly but think its fine to * always give predictable behavior in weight paint mode - campbell */ - if (!extend || ((ob_act && (ob_act != ob) && (ob_act->mode & OB_MODE_WEIGHT_PAINT) == 0))) { + if ((!extend && !deselect && !toggle)|| ((ob_act && (ob_act != ob) && (ob_act->mode & OB_MODE_WEIGHT_PAINT) == 0))) { ED_pose_deselectall(ob, 0); nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); arm->act_bone = nearBone; @@ -4503,25 +4526,34 @@ //select_actionchannel_by_name(ob->action, nearBone->name, 1); } else { - if (nearBone->flag & BONE_SELECTED) { - /* if not active, we make it active */ - if (nearBone != arm->act_bone) { - arm->act_bone = nearBone; + if (extend) { + nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + arm->act_bone = nearBone; + } + else if (deselect) { + nearBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + } + else if (toggle) { + if (nearBone->flag & BONE_SELECTED) { + /* if not active, we make it active */ + if (nearBone != arm->act_bone) { + arm->act_bone = nearBone; + } + else { + nearBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + + // XXX old cruft! use notifiers instead + //select_actionchannel_by_name(ob->action, nearBone->name, 0); + } } else { - nearBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - + nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + arm->act_bone = nearBone; + // XXX old cruft! use notifiers instead - //select_actionchannel_by_name(ob->action, nearBone->name, 0); + //select_actionchannel_by_name(ob->action, nearBone->name, 1); } - } - else { - nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - arm->act_bone = nearBone; - - // XXX old cruft! use notifiers instead - //select_actionchannel_by_name(ob->action, nearBone->name, 1); - } + } } /* in weightpaint we select the associated vertex group too */ Index: source/blender/editors/metaball/mball_edit.c =================================================================== --- source/blender/editors/metaball/mball_edit.c (revision 46963) +++ source/blender/editors/metaball/mball_edit.c (working copy) @@ -415,7 +415,7 @@ /* Select MetaElement with mouse click (user can select radius circle or * stiffness circle) */ -int mouse_mball(bContext *C, const int mval[2], int extend) +int mouse_mball(bContext *C, const int mval[2], int extend, int deselect, int toggle) { static MetaElem *startelem = NULL; Object *obedit = CTX_data_edit_object(C); @@ -467,7 +467,19 @@ /* When some metaelem was found, then it is necessary to select or * deselect it. */ if (act) { - if (extend == 0) { + if (extend) { + act->flag |= SELECT; + } + else if (deselect) { + act->flag &= ~SELECT; + } + else if (toggle) { + if (act->flag & SELECT) + act->flag &= ~SELECT; + else + act->flag |= SELECT; + } + else { /* Deselect all existing metaelems */ ml = mb->editelems->first; while (ml) { @@ -477,12 +489,7 @@ /* Select only metaelem clicked on */ act->flag |= SELECT; } - else { - if (act->flag & SELECT) - act->flag &= ~SELECT; - else - act->flag |= SELECT; - } + mb->lastelem = act; WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb); Index: source/blender/editors/curve/editcurve.c =================================================================== --- source/blender/editors/curve/editcurve.c (revision 46963) +++ source/blender/editors/curve/editcurve.c (working copy) @@ -4126,7 +4126,7 @@ /***************** pick select from 3d view **********************/ -int mouse_nurb(bContext *C, const int mval[2], int extend) +int mouse_nurb(bContext *C, const int mval[2], int extend, int deselect, int toggle) { Object *obedit = CTX_data_edit_object(C); Curve *cu = obedit->data; @@ -4146,12 +4146,8 @@ hand = findnearestNurbvert(&vc, 1, location, &nu, &bezt, &bp); if (bezt || bp) { - if (extend == 0) { - - setflagsNurb(editnurb, 0); - + if (extend) { if (bezt) { - if (hand == 1) { select_beztriple(bezt, SELECT, 1, HIDDEN); cu->lastsel = bezt; @@ -4167,11 +4163,28 @@ cu->lastsel = bp; select_bpoint(bp, SELECT, 1, HIDDEN); } - } - else { + else if (deselect) { if (bezt) { if (hand == 1) { + select_beztriple(bezt, DESELECT, 1, HIDDEN); + if (bezt == cu->lastsel) cu->lastsel = NULL; + } + else if (hand == 0) { + bezt->f1 &= ~SELECT; + } + else { + bezt->f3 &= ~SELECT; + } + } + else { + select_bpoint(bp, DESELECT, 1, HIDDEN); + if (cu->lastsel == bp) cu->lastsel = NULL; + } + } + else if (toggle) { + if (bezt) { + if (hand == 1) { if (bezt->f2 & SELECT) { select_beztriple(bezt, DESELECT, 1, HIDDEN); if (bezt == cu->lastsel) cu->lastsel = NULL; @@ -4198,7 +4211,27 @@ cu->lastsel = bp; } } + } + else { + setflagsNurb(editnurb, 0); + if (bezt) { + + if (hand == 1) { + select_beztriple(bezt, SELECT, 1, HIDDEN); + cu->lastsel = bezt; + } + else { + if (hand == 0) bezt->f1 |= SELECT; + else bezt->f3 |= SELECT; + + cu->lastsel = NULL; + } + } + else { + cu->lastsel = bp; + select_bpoint(bp, SELECT, 1, HIDDEN); + } } if (nu != get_actNurb(obedit)) Index: source/blender/editors/mesh/editmesh_select.c =================================================================== --- source/blender/editors/mesh/editmesh_select.c (revision 46963) +++ source/blender/editors/mesh/editmesh_select.c (working copy) @@ -1454,7 +1454,7 @@ /* ************************************************** */ /* here actual select happens */ /* gets called via generic mouse select operator */ -int mouse_mesh(bContext *C, const int mval[2], short extend) +int mouse_mesh(bContext *C, const int mval[2], short extend, short deselect, short toggle) { ViewContext vc; BMVert *eve = NULL; @@ -1468,40 +1468,87 @@ if (unified_findnearest(&vc, &eve, &eed, &efa)) { - if (extend == 0) EDBM_flag_disable_all(vc.em, BM_ELEM_SELECT); + // Deselect everything + if (extend == 0 && deselect == 0 && toggle == 0) + EDBM_flag_disable_all(vc.em, BM_ELEM_SELECT); if (efa) { - /* set the last selected face */ - BM_active_face_set(vc.em->bm, efa); - - if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) { + if (extend) { + // set the last selected face + BM_active_face_set(vc.em->bm, efa); + + // Work-around: deselect first, so we can guarantee it will + // be active even if it was already selected + BM_select_history_remove(vc.em->bm, efa); + BM_face_select_set(vc.em->bm, efa, FALSE); BM_select_history_store(vc.em->bm, efa); BM_face_select_set(vc.em->bm, efa, TRUE); } - else if (extend) { + else if (deselect) { BM_select_history_remove(vc.em->bm, efa); BM_face_select_set(vc.em->bm, efa, FALSE); } + else { + // set the last selected face + BM_active_face_set(vc.em->bm, efa); + + if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) { + BM_select_history_store(vc.em->bm, efa); + BM_face_select_set(vc.em->bm, efa, TRUE); + } + else if (extend) { + BM_select_history_remove(vc.em->bm, efa); + BM_face_select_set(vc.em->bm, efa, FALSE); + } + } } else if (eed) { - if (!BM_elem_flag_test(eed, BM_ELEM_SELECT)) { + if (extend) { + // Work-around: deselect first, so we can guarantee it will + // be active even if it was already selected + BM_select_history_remove(vc.em->bm, eed); + BM_edge_select_set(vc.em->bm, eed, FALSE); BM_select_history_store(vc.em->bm, eed); BM_edge_select_set(vc.em->bm, eed, TRUE); } - else if (extend) { + else if (deselect) { BM_select_history_remove(vc.em->bm, eed); BM_edge_select_set(vc.em->bm, eed, FALSE); } + else { + if (!BM_elem_flag_test(eed, BM_ELEM_SELECT)) { + BM_select_history_store(vc.em->bm, eed); + BM_edge_select_set(vc.em->bm, eed, TRUE); + } + else if (toggle) { + BM_select_history_remove(vc.em->bm, eed); + BM_edge_select_set(vc.em->bm, eed, FALSE); + } + } } else if (eve) { - if (!BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + if (extend) { + // Work-around: deselect first, so we can guarantee it will + // be active even if it was already selected + BM_select_history_remove(vc.em->bm, eve); + BM_vert_select_set(vc.em->bm, eve, FALSE); BM_select_history_store(vc.em->bm, eve); BM_vert_select_set(vc.em->bm, eve, TRUE); } - else if (extend) { + else if (deselect) { BM_select_history_remove(vc.em->bm, eve); BM_vert_select_set(vc.em->bm, eve, FALSE); } + else { + if (!BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + BM_select_history_store(vc.em->bm, eve); + BM_vert_select_set(vc.em->bm, eve, TRUE); + } + else if (toggle) { + BM_select_history_remove(vc.em->bm, eve); + BM_vert_select_set(vc.em->bm, eve, FALSE); + } + } } EDBM_selectmode_flush(vc.em); Index: source/blender/editors/mesh/editface.c =================================================================== --- source/blender/editors/mesh/editface.c (revision 46963) +++ source/blender/editors/mesh/editface.c (working copy) @@ -509,7 +509,7 @@ } #endif -int paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], int extend) +int paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], int extend, int deselect, int toggle) { Mesh *me; MPoly *mpoly, *mpoly_sel; @@ -530,7 +530,7 @@ /* clear flags */ mpoly = me->mpoly; a = me->totpoly; - if (!extend) { + if (!extend && !deselect && !toggle) { while (a--) { mpoly->flag &= ~ME_FACE_SEL; mpoly++; @@ -540,6 +540,12 @@ me->act_face = (int)index; if (extend) { + mpoly_sel->flag |= ME_FACE_SEL; + } + else if (deselect) { + mpoly_sel->flag &= ~ME_FACE_SEL; + } + else if (toggle) { if (mpoly_sel->flag & ME_FACE_SEL) mpoly_sel->flag &= ~ME_FACE_SEL; else Index: source/blender/editors/object/object_lattice.c =================================================================== --- source/blender/editors/object/object_lattice.c (revision 46963) +++ source/blender/editors/object/object_lattice.c (working copy) @@ -335,7 +335,7 @@ return data.bp; } -int mouse_lattice(bContext *C, const int mval[2], int extend) +int mouse_lattice(bContext *C, const int mval[2], int extend, int deselect, int toggle) { ViewContext vc; BPoint *bp = NULL; @@ -344,12 +344,20 @@ bp = findnearestLattvert(&vc, mval, 1); if (bp) { - if (extend == 0) { - ED_setflagsLatt(vc.obedit, 0); + if (extend) { + bp->f1 |= SELECT; + } + else if (deselect) { + bp->f1 &= ~SELECT; + } + else if (toggle) { + bp->f1 ^= SELECT; /* swap */ + } + else + { + ED_setflagsLatt(vc.obedit, 0); bp->f1 |= SELECT; } - else - bp->f1 ^= SELECT; /* swap */ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);