Index: source/blender/editors/armature/armature_intern.h =================================================================== --- source/blender/editors/armature/armature_intern.h (revision 57525) +++ source/blender/editors/armature/armature_intern.h (working copy) @@ -63,6 +63,8 @@ void ARMATURE_OT_select_all(struct wmOperatorType *ot); void ARMATURE_OT_select_inverse(struct wmOperatorType *ot); +void ARMATURE_OT_select_more(struct wmOperatorType *ot); +void ARMATURE_OT_select_less(struct wmOperatorType *ot); void ARMATURE_OT_select_hierarchy(struct wmOperatorType *ot); void ARMATURE_OT_select_linked(struct wmOperatorType *ot); void ARMATURE_OT_select_similar(struct wmOperatorType *ot); Index: source/blender/editors/armature/armature_select.c =================================================================== --- source/blender/editors/armature/armature_select.c (revision 57525) +++ source/blender/editors/armature/armature_select.c (working copy) @@ -35,6 +35,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_linklist.h" #include "BKE_context.h" #include "BKE_deform.h" @@ -655,6 +656,151 @@ WM_operator_properties_select_all(ot); } +/* Get the first available child of an editbone */ +static EditBone *editbone_get_child(bArmature *arm, EditBone *pabone, short use_visibility) +{ + EditBone *curbone, *chbone = NULL; + + for (curbone = arm->edbo->first; curbone; curbone = curbone->next) { + if (curbone->parent == pabone) { + if (use_visibility) { + if ((arm->layer & curbone->layer) && !(pabone->flag & BONE_HIDDEN_A)) { + chbone = curbone; + } + } + else + chbone = curbone; + } + } + + return chbone; +} + + +static EditBone *editbone_get_next_sibling(bArmature *arm, EditBone *parent, EditBone *current_sibling){ + EditBone *eb = NULL, *first_bone = NULL; + + if (!current_sibling){ + //We haven't found the first child yet. Look for it. + first_bone = arm->edbo->first; + } else { + //We will begin from where we left in the previous call + first_bone = current_sibling->next; + } + + for (eb = first_bone; eb && eb->parent != parent; eb = eb ->next){} + + return eb; +} + +static int armature_de_select_more_exec(bContext *C, wmOperator *op) +{ + Object *obedit = CTX_data_edit_object(C); + bArmature *arm = (bArmature *)obedit->data; + LinkNode *iter, *linklist = NULL; + EditBone *eb, *temp_sibling; + + CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) + { + if (ebone->flag & BONE_SELECTED){ + BLI_linklist_prepend(&linklist, ebone); + } + } + CTX_DATA_END; + + eb = NULL; + temp_sibling = NULL; + for(iter = linklist; iter; iter = iter->next){ + eb = iter->link; + if (eb->parent) + eb->parent->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + + while ((temp_sibling = editbone_get_next_sibling(arm, eb, temp_sibling))){ + temp_sibling->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + } + } + + BLI_linklist_free(linklist,NULL); + + WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit); + + return OPERATOR_FINISHED; +} + +void ARMATURE_OT_select_more(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select More"; + ot->idname = "ARMATURE_OT_select_more"; + ot->description = "Select those bones connected to the initial selection"; + + /* api callbacks */ + ot->exec = armature_de_select_more_exec; + ot->poll = ED_operator_editarmature; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + +} + +static int armature_de_select_less_exec(bContext *C, wmOperator *op) +{ + Object *obedit = CTX_data_edit_object(C); + bArmature *arm = (bArmature *)obedit->data; + LinkNode *iter, *linklist = NULL; + EditBone *temp_sibling = NULL; + short to_be_unselected = 0; + + CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) + { + to_be_unselected = 0; + if (ebone->parent && !(ebone->parent->flag & BONE_SELECTED)) { + //If the parent is not selected, then mark this bone to be unselected + to_be_unselected = 1; + + } else { + //If any of its children is not selected, then the bone will be unselected too + + while ((temp_sibling = editbone_get_next_sibling(arm, ebone, temp_sibling)) && !to_be_unselected){ + if (!(temp_sibling->flag & BONE_SELECTED)) + to_be_unselected = 1; + } + + } + + if (to_be_unselected) + BLI_linklist_prepend(&linklist, ebone); + } + CTX_DATA_END; + + for(iter = linklist; iter; iter = iter->next){ + ((EditBone *)iter->link)->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + } + + BLI_linklist_free(linklist,NULL); + + WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit); + + return OPERATOR_FINISHED; +} + + +void ARMATURE_OT_select_less(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Less"; + ot->idname = "ARMATURE_OT_select_less"; + ot->description = "Deselect those bones at the boundary of each selection region"; + + /* api callbacks */ + ot->exec = armature_de_select_less_exec; + ot->poll = ED_operator_editarmature; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + +} + enum { SIMEDBONE_LENGTH = 1, SIMEDBONE_DIRECTION, @@ -842,26 +988,6 @@ /* ********************* select hierarchy operator ************** */ -/* Get the first available child of an editbone */ -static EditBone *editbone_get_child(bArmature *arm, EditBone *pabone, short use_visibility) -{ - EditBone *curbone, *chbone = NULL; - - for (curbone = arm->edbo->first; curbone; curbone = curbone->next) { - if (curbone->parent == pabone) { - if (use_visibility) { - if ((arm->layer & curbone->layer) && !(pabone->flag & BONE_HIDDEN_A)) { - chbone = curbone; - } - } - else - chbone = curbone; - } - } - - return chbone; -} - static int armature_select_hierarchy_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); Index: source/blender/editors/armature/armature_ops.c =================================================================== --- source/blender/editors/armature/armature_ops.c (revision 57525) +++ source/blender/editors/armature/armature_ops.c (working copy) @@ -59,6 +59,8 @@ WM_operatortype_append(ARMATURE_OT_select_all); WM_operatortype_append(ARMATURE_OT_select_inverse); + WM_operatortype_append(ARMATURE_OT_select_more); + WM_operatortype_append(ARMATURE_OT_select_less); WM_operatortype_append(ARMATURE_OT_select_hierarchy); WM_operatortype_append(ARMATURE_OT_select_linked); WM_operatortype_append(ARMATURE_OT_select_similar); @@ -258,6 +260,9 @@ RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_CHILD); RNA_boolean_set(kmi->ptr, "extend", TRUE); + WM_keymap_add_item(keymap, "ARMATURE_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "ARMATURE_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "ARMATURE_OT_select_similar", GKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "ARMATURE_OT_select_linked", LKEY, KM_PRESS, 0, 0); Index: source/blender/editors/object/object_ops.c =================================================================== --- source/blender/editors/object/object_ops.c (revision 57525) +++ source/blender/editors/object/object_ops.c (working copy) @@ -212,6 +212,8 @@ WM_operatortype_append(LATTICE_OT_select_all); WM_operatortype_append(LATTICE_OT_select_ungrouped); + WM_operatortype_append(LATTICE_OT_select_more); + WM_operatortype_append(LATTICE_OT_select_less); WM_operatortype_append(LATTICE_OT_make_regular); WM_operatortype_append(LATTICE_OT_flip); @@ -426,6 +428,9 @@ WM_keymap_add_item(keymap, "LATTICE_OT_flip", FKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "LATTICE_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "LATTICE_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0); + /* menus */ WM_keymap_add_menu(keymap, "VIEW3D_MT_hook", HKEY, KM_PRESS, KM_CTRL, 0); Index: source/blender/editors/object/object_lattice.c =================================================================== --- source/blender/editors/object/object_lattice.c (revision 57525) +++ source/blender/editors/object/object_lattice.c (working copy) @@ -35,6 +35,7 @@ #include "MEM_guardedalloc.h" #include "BLI_listbase.h" +#include "BLI_linklist.h" #include "BLI_math.h" #include "BLI_utildefines.h" @@ -204,7 +205,8 @@ bp = lt->editlatt->latt->def; a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; - + + //There are as many points in the bp-pointed array as "a" value while (a--) { if (bp->hide == 0) { if (bp->f1 & SELECT) { @@ -259,6 +261,163 @@ WM_operator_properties_select_all(ot); } +/* Helper macro for accessing item at index (u, v, w) + * < lt: (Lattice) + * < U: (int) u-axis coordinate of point + * < V: (int) v-axis coordinate of point + * < W: (int) w-axis coordinate of point + * < dimU: (int) number of points per row or number of columns (U-Axis) + * < dimV: (int) number of rows (V-Axis) + * > returns: (BPoint *) pointer to BPoint at this index + */ +#define LATTICE_PT(lt, U, V, W, dimU, dimV) \ +( (lt)->def + \ +((dimU) * (dimV)) * (W) + \ +(dimU) * (V) + \ +(U) \ +) + +/************************** Select more/less Operators *************************/ + +struct LatticePoint { + BPoint *bp; + int u, v, w; +}; + +static void select_near_edges(Lattice * lt, struct LatticePoint lp) +{ + + if (lp.u - 1 >= 0) LATTICE_PT(lt, lp.u - 1, lp.v, lp.w, lt->pntsu, lt->pntsv )->f1 |= SELECT; + if (lp.u + 1 < lt->pntsu) LATTICE_PT(lt, lp.u + 1, lp.v, lp.w, lt->pntsu, lt->pntsv )->f1 |= SELECT; + + if (lp.v - 1 >= 0) LATTICE_PT(lt, lp.u, lp.v - 1, lp.w, lt->pntsu, lt->pntsv )->f1 |= SELECT; + if (lp.v + 1 < lt->pntsv) LATTICE_PT(lt, lp.u, lp.v + 1, lp.w, lt->pntsu, lt->pntsv )->f1 |= SELECT; + + if (lp.w - 1 >= 0) LATTICE_PT(lt, lp.u, lp.v, lp.w - 1, lt->pntsu, lt->pntsv )->f1 |= SELECT; + if (lp.w + 1 < lt->pntsw) LATTICE_PT(lt, lp.u, lp.v, lp.w + 1, lt->pntsu, lt->pntsv )->f1 |= SELECT; + +} + +static int lattice_select_more_exec(bContext *C, wmOperator *op) +{ + int u, v, w, i = 0; + Object *obedit = CTX_data_edit_object(C); + Lattice *lt = ((Lattice *)(obedit->data))->editlatt->latt; + + BPoint *bp = lt->def; + LinkNode *iter, *linklist = NULL; + struct LatticePoint * lp = NULL; + + //Add vertices currently selected to a list + for (w = 0; w < lt->pntsw; w++){ + for (v = 0; v < lt->pntsv; v++){ + for (u = 0; u < lt->pntsu; u++){ + if (bp[i].f1 & SELECT) { + lp = MEM_mallocN(sizeof(struct LatticePoint), "lattice_point"); + lp->u = u; lp->v = v; lp->w = w; + lp->bp = &bp[i]; + BLI_linklist_prepend(&linklist, lp); + } + i++; + } + } + } + + //Traverse the list, setting as selected all those vertices adjacent to those already selected + lp = NULL; + for(iter = linklist; iter; iter = iter->next){ + lp = iter->link; + select_near_edges(lt, *lp); + } + + BLI_linklist_freeN(linklist); + + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + + return OPERATOR_FINISHED; +} + +void LATTICE_OT_select_more(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select More"; + ot->idname = "LATTICE_OT_select_more"; + ot->description = "Select more vertices connected to initial selection"; + + /* api callbacks */ + ot->exec = lattice_select_more_exec; + ot->poll = ED_operator_editlattice; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + +} + +static int unselectable_vertex_on_less(Lattice * lt, BPoint * p, int u, int v, int w) +{ + + if (!(p->f1 & SELECT)) return 0; + + if (u + 1 < lt->pntsu && !(LATTICE_PT(lt, u + 1, v, w, lt->pntsu, lt->pntsv )->f1 & SELECT)) return 1; + if (u - 1 >= 0 && !(LATTICE_PT(lt, u - 1, v, w, lt->pntsu, lt->pntsv )->f1 & SELECT)) return 1; + + if (v + 1 < lt->pntsv && !(LATTICE_PT(lt, u, v + 1, w, lt->pntsu, lt->pntsv )->f1 & SELECT)) return 1; + if (v - 1 >= 0 && !(LATTICE_PT(lt, u, v - 1, w, lt->pntsu, lt->pntsv )->f1 & SELECT)) return 1; + + if (w + 1 < lt->pntsw && !(LATTICE_PT(lt, u, v, w + 1, lt->pntsu, lt->pntsv )->f1 & SELECT)) return 1; + if (w - 1 >= 0 && !(LATTICE_PT(lt, u, v, w - 1, lt->pntsu, lt->pntsv )->f1 & SELECT)) return 1; + + return 0; +} + +static int lattice_select_less_exec(bContext *C, wmOperator *op){ + int u, v, w, i = 0; + Object *obedit = CTX_data_edit_object(C); + Lattice *lt = ((Lattice *)(obedit->data))->editlatt->latt; + + BPoint *bp = lt->def; + LinkNode *iter, *linklist = NULL; + + //Add vertices currently selected to a list + for (w = 0; w < lt->pntsw; w++){ + for (v = 0; v < lt->pntsv; v++){ + for (u = 0; u < lt->pntsu; u++){ + if (unselectable_vertex_on_less(lt, &bp[i], u, v, w )) { + BLI_linklist_prepend(&linklist, &bp[i]); + } + i++; + } + } + } + + //Traverse the list, setting as selected all those vertices adjacent to those already selected + for(iter = linklist; iter; iter = iter->next){ + ((BPoint *)iter->link)->f1 ^= SELECT; + } + + BLI_linklist_free(linklist,NULL); + + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + + return OPERATOR_FINISHED; +} + +void LATTICE_OT_select_less(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Less"; + ot->idname = "LATTICE_OT_select_less"; + ot->description = "Deselect vertices at the boundary of each selection region"; + + /* api callbacks */ + ot->exec = lattice_select_less_exec; + ot->poll = ED_operator_editlattice; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + +} + /************************** Select Ungrouped Verts Operator *************************/ static int lattice_select_ungrouped_exec(bContext *C, wmOperator *op) @@ -368,21 +527,6 @@ LATTICE_FLIP_W = 2 } eLattice_FlipAxes; -/* Helper macro for accessing item at index (u, v, w) - * < lt: (Lattice) - * < U: (int) u-axis coordinate of point - * < V: (int) v-axis coordinate of point - * < W: (int) w-axis coordinate of point - * < dimU: (int) number of points per row or number of columns (U-Axis) - * < dimV: (int) number of rows (V-Axis) - * > returns: (BPoint *) pointer to BPoint at this index - */ -#define LATTICE_PT(lt, U, V, W, dimU, dimV) \ - ( (lt)->def + \ - ((dimU) * (dimV)) * (W) + \ - (dimU) * (V) + \ - (U) \ - ) /* Flip midpoint value so that relative distances between midpoint and neighbour-pair is maintained * ! Assumes that uvw <=> xyz (i.e. axis-aligned index-axes with coordinate-axes) Index: source/blender/editors/object/object_intern.h =================================================================== --- source/blender/editors/object/object_intern.h (revision 57525) +++ source/blender/editors/object/object_intern.h (working copy) @@ -141,6 +141,8 @@ void LATTICE_OT_select_ungrouped(struct wmOperatorType *ot); void LATTICE_OT_make_regular(struct wmOperatorType *ot); void LATTICE_OT_flip(struct wmOperatorType *ot); +void LATTICE_OT_select_more(struct wmOperatorType *ot); +void LATTICE_OT_select_less(struct wmOperatorType *ot); /* object_group.c */ void GROUP_OT_create(struct wmOperatorType *ot); Index: release/scripts/startup/bl_ui/space_view3d.py =================================================================== --- release/scripts/startup/bl_ui/space_view3d.py (revision 57525) +++ release/scripts/startup/bl_ui/space_view3d.py (working copy) @@ -720,6 +720,11 @@ layout.operator("view3d.select_circle") layout.separator() + + layout.operator("lattice.select_less", text="Less") + layout.operator("lattice.select_more", text="More") + + layout.separator() layout.operator("lattice.select_all").action = 'TOGGLE' layout.operator("lattice.select_all", text="Inverse").action = 'INVERT' @@ -744,7 +749,12 @@ layout.operator("armature.select_all", text="Inverse").action = 'INVERT' layout.separator() + + layout.operator("armature.select_less", text="Less") + layout.operator("armature.select_more", text="More") + layout.separator() + layout.operator("armature.select_hierarchy", text="Parent").direction = 'PARENT' layout.operator("armature.select_hierarchy", text="Child").direction = 'CHILD'