Index: release/scripts/startup/bl_ui/space_view3d.py =================================================================== --- release/scripts/startup/bl_ui/space_view3d.py (revision 57852) +++ release/scripts/startup/bl_ui/space_view3d.py (working copy) @@ -723,6 +723,11 @@ 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' Index: source/blender/blenkernel/BKE_lattice.h =================================================================== --- source/blender/blenkernel/BKE_lattice.h (revision 57852) +++ source/blender/blenkernel/BKE_lattice.h (working copy) @@ -42,6 +42,22 @@ struct BPoint; struct MDeformVert; +/* The following two structures are not meant to be saved on disc, so they are not declared in DNA file */ + +/* Stores the selection status of a Lattice object */ +typedef struct LatticeSelectionMap { + /* Actually, this field is a BLI_bitmap, + * but because that header is not included in this file, we declare it as void */ + void *selectionmap; + struct Lattice *lt; +} LatticeSelectionMap; + +/* Used to traverse the selection saved on a LatticeSelectionMap */ +typedef struct LatticeSelectionIter { + int u, v, w; + int index_current; +} LatticeSelectionIter; + void BKE_lattice_resize(struct Lattice *lt, int u, int v, int w, struct Object *ltOb); struct Lattice *BKE_lattice_add(struct Main *bmain, const char *name); struct Lattice *BKE_lattice_copy(struct Lattice *lt); @@ -82,6 +98,14 @@ void BKE_lattice_center_bounds(struct Lattice *lt, float cent[3]); void BKE_lattice_translate(struct Lattice *lt, float offset[3], int do_keys); +LatticeSelectionMap *BKE_lattice_selection_map_new(struct Lattice *lt); +bool BKE_lattice_selection_map_query_uvw(LatticeSelectionMap *lsm, int u, int v, int w); +bool BKE_lattice_selection_map_query(LatticeSelectionMap *lsm, int index); +void BKE_lattice_selection_map_free(LatticeSelectionMap *lsm); +LatticeSelectionIter *BKE_lattice_selection_begin_iter(void); +bool BKE_lattice_selection_iter_through(LatticeSelectionMap *lsm, LatticeSelectionIter *lsi, int selection_flag); +void BKE_lattice_selection_free_iter(struct LatticeSelectionIter *lsi); + int BKE_lattice_index_from_uvw(struct Lattice *lt, const int u, const int v, const int w); void BKE_lattice_index_to_uvw(struct Lattice *lt, const int index, int *r_u, int *r_v, int *r_w); Index: source/blender/blenkernel/intern/lattice.c =================================================================== --- source/blender/blenkernel/intern/lattice.c (revision 57852) +++ source/blender/blenkernel/intern/lattice.c (working copy) @@ -39,6 +39,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLI_bitmap.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -1107,3 +1108,83 @@ } } +LatticeSelectionMap *BKE_lattice_selection_map_new(Lattice *lt) +{ + int u, v, w, index; + LatticeSelectionMap * ret; + BPoint *bp = lt->def; + + ret = MEM_mallocN(sizeof(LatticeSelectionMap), "Lattice selection map"); + + ret->lt = lt; + + ret->selectionmap = BLI_BITMAP_NEW(lt->pntsu * lt->pntsv * lt->pntsw, "lattice selection bitmap"); + + //Set in the bitmap vertices currently selected + for (w = 0; w < lt->pntsw; w++) { + for (v = 0; v < lt->pntsv; v++) { + for (u = 0; u < lt->pntsu; u++) { + index = BKE_lattice_index_from_uvw(lt, u, v, w); + if (bp[index].f1 & SELECT) { + BLI_BITMAP_SET((unsigned int *)ret->selectionmap, index); + } + } + } + } + + return ret; +} + +bool BKE_lattice_selection_map_query(LatticeSelectionMap *lsm, int index) +{ + return BLI_BITMAP_GET_BOOL((unsigned int *)lsm->selectionmap, index); +} + +bool BKE_lattice_selection_map_query_uvw(LatticeSelectionMap *lsm, int u, int v, int w) +{ + return BKE_lattice_selection_map_query(lsm, BKE_lattice_index_from_uvw(lsm->lt, u, v, w)); +} + +void BKE_lattice_selection_map_free(LatticeSelectionMap *lsm) +{ + MEM_freeN(lsm->selectionmap); + MEM_freeN(lsm); +} + +LatticeSelectionIter *BKE_lattice_selection_begin_iter(void) +{ + LatticeSelectionIter *ret = MEM_mallocN(sizeof(LatticeSelectionIter), "Lattice selection iterator"); + ret->u = 0; ret->v = 0; ret->w = 0; + ret->index_current = 0; + return ret; +} + +bool BKE_lattice_selection_iter_through(LatticeSelectionMap *lsm, LatticeSelectionIter *lsi, int selection_flag) +{ + int count, max; + bool ended = false; + + count = lsi->index_current; + + max = lsm->lt->pntsu * lsm->lt->pntsv * lsm->lt->pntsw; + while (count < max && !ended) { + const bool selected = BKE_lattice_selection_map_query(lsm, count); + const bool b1 = selection_flag == SELECT && selected; + const bool b2 = selection_flag != SELECT && !selected; + + if (b1 || b2) { + ended = true; + BKE_lattice_index_to_uvw(lsm->lt, count, &(lsi->u), &(lsi->v), &(lsi->w)); + } + count++; + } + + lsi->index_current = count; + + return ended; +} + +void BKE_lattice_selection_free_iter(LatticeSelectionIter *lsi) +{ + MEM_freeN(lsi); +} Index: source/blender/blenlib/BLI_bitmap.h =================================================================== --- source/blender/blenlib/BLI_bitmap.h (revision 57852) +++ source/blender/blenlib/BLI_bitmap.h (working copy) @@ -56,6 +56,10 @@ ((_bitmap)[(_index) >> BLI_BITMAP_POWER] & \ (1 << ((_index) & BLI_BITMAP_MASK))) +/* Returns 1 if the bit pointed by index is set, and 0 otherwise */ +#define BLI_BITMAP_GET_BOOL(_bitmap, _index) \ + ((BLI_BITMAP_GET(_bitmap, _index) != 0)) + /* set the value of a single bit at '_index' */ #define BLI_BITMAP_SET(_bitmap, _index) \ ((_bitmap)[(_index) >> BLI_BITMAP_POWER] |= \ Index: source/blender/editors/object/object_intern.h =================================================================== --- source/blender/editors/object/object_intern.h (revision 57852) +++ 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: source/blender/editors/object/object_lattice.c =================================================================== --- source/blender/editors/object/object_lattice.c (revision 57852) +++ source/blender/editors/object/object_lattice.c (working copy) @@ -35,6 +35,7 @@ #include "MEM_guardedalloc.h" #include "BLI_listbase.h" +#include "BLI_bitmap.h" #include "BLI_math.h" #include "BLI_utildefines.h" @@ -205,6 +206,7 @@ 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,106 @@ WM_operator_properties_select_all(ot); } +/************************** Select more/less Operators *************************/ + +static void lattice_select_neighbours__internal(Lattice *lt, int u, int v, int w) +{ + BPoint *bp = lt->def; + if (u - 1 >= 0) bp[BKE_lattice_index_from_uvw(lt, u - 1, v, w)].f1 |= SELECT; + if (u + 1 < lt->pntsu) bp[BKE_lattice_index_from_uvw(lt, u + 1, v, w)].f1 |= SELECT; + + if (v - 1 >= 0) bp[BKE_lattice_index_from_uvw(lt, u, v - 1, w)].f1 |= SELECT; + if (v + 1 < lt->pntsv) bp[BKE_lattice_index_from_uvw(lt, u, v + 1, w)].f1 |= SELECT; + + if (w - 1 >= 0) bp[BKE_lattice_index_from_uvw(lt, u, v, w - 1)].f1 |= SELECT; + if (w + 1 < lt->pntsw) bp[BKE_lattice_index_from_uvw(lt, u, v, w + 1)].f1 |= SELECT; +} + +static void lattice_deselect_neighbours__internal(Lattice *lt, int u, int v, int w) +{ + BPoint *bp = lt->def; + if (u - 1 >= 0) bp[BKE_lattice_index_from_uvw(lt, u - 1, v, w)].f1 &= ~SELECT; + if (u + 1 < lt->pntsu) bp[BKE_lattice_index_from_uvw(lt, u + 1, v, w)].f1 &= ~SELECT; + + if (v - 1 >= 0) bp[BKE_lattice_index_from_uvw(lt, u, v - 1, w)].f1 &= ~SELECT; + if (v + 1 < lt->pntsv) bp[BKE_lattice_index_from_uvw(lt, u, v + 1, w)].f1 &= ~SELECT; + + if (w - 1 >= 0) bp[BKE_lattice_index_from_uvw(lt, u, v, w - 1)].f1 &= ~SELECT; + if (w + 1 < lt->pntsw) bp[BKE_lattice_index_from_uvw(lt, u, v, w + 1)].f1 &= ~SELECT; +} + +static int lattice_select_more_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *obedit = CTX_data_edit_object(C); + Lattice *lt = ((Lattice *)(obedit->data))->editlatt->latt; + + LatticeSelectionMap *lsm = BKE_lattice_selection_map_new(lt); + LatticeSelectionIter *lsi = BKE_lattice_selection_begin_iter(); + + while (BKE_lattice_selection_iter_through(lsm, lsi, SELECT)) { + lattice_select_neighbours__internal(lt, lsi->u, lsi->v, lsi->w); + } + + BKE_lattice_selection_free_iter(lsi); + BKE_lattice_selection_map_free(lsm); + + 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 lattice_select_less_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *obedit = CTX_data_edit_object(C); + Lattice *lt = ((Lattice *)(obedit->data))->editlatt->latt; + + LatticeSelectionMap *lsm = BKE_lattice_selection_map_new(lt); + LatticeSelectionIter *lsi = BKE_lattice_selection_begin_iter(); + + while (BKE_lattice_selection_iter_through(lsm, lsi, 0)) { + lattice_deselect_neighbours__internal(lt, lsi->u, lsi->v, lsi->w); + } + + BKE_lattice_selection_free_iter(lsi); + BKE_lattice_selection_map_free(lsm); + + 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) Index: source/blender/editors/object/object_ops.c =================================================================== --- source/blender/editors/object/object_ops.c (revision 57852) +++ source/blender/editors/object/object_ops.c (working copy) @@ -217,6 +217,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); @@ -431,6 +433,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);