diff options
Diffstat (limited to 'source/blender/editors/mesh/editmesh_select.c')
-rw-r--r-- | source/blender/editors/mesh/editmesh_select.c | 594 |
1 files changed, 390 insertions, 204 deletions
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index a98345cacec..9474c051cee 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -40,9 +40,9 @@ #include "BKE_context.h" #include "BKE_displist.h" -#include "BKE_depsgraph.h" #include "BKE_report.h" #include "BKE_paint.h" +#include "BKE_mesh.h" #include "BKE_tessmesh.h" #include "IMB_imbuf_types.h" @@ -56,9 +56,7 @@ #include "ED_mesh.h" #include "ED_screen.h" -#include "ED_util.h" #include "ED_uvedit.h" -#include "ED_object.h" #include "ED_view3d.h" #include "BIF_gl.h" @@ -66,6 +64,9 @@ #include "DNA_scene_types.h" #include "DNA_object_types.h" #include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "GPU_extensions.h" #include "mesh_intern.h" @@ -73,7 +74,7 @@ /* ****************************** MIRROR **************** */ -void EDBM_select_mirrored(Object *UNUSED(obedit), BMEditMesh *em, int extend) +void EDBM_select_mirrored(Object *UNUSED(obedit), BMEditMesh *em, bool extend) { BMVert *v1, *v2; BMIter iter; @@ -87,7 +88,7 @@ void EDBM_select_mirrored(Object *UNUSED(obedit), BMEditMesh *em, int extend) } } - EDBM_verts_mirror_cache_begin(em, TRUE); + EDBM_verts_mirror_cache_begin(em, true); if (!extend) EDBM_flag_disable_all(em, BM_ELEM_SELECT); @@ -98,7 +99,7 @@ void EDBM_select_mirrored(Object *UNUSED(obedit), BMEditMesh *em, int extend) v2 = EDBM_verts_mirror_get(em, v1); if (v2 && !BM_elem_flag_test(v2, BM_ELEM_HIDDEN)) { - BM_vert_select_set(em->bm, v2, TRUE); + BM_vert_select_set(em->bm, v2, true); } } @@ -107,21 +108,23 @@ void EDBM_select_mirrored(Object *UNUSED(obedit), BMEditMesh *em, int extend) void EDBM_automerge(Scene *scene, Object *obedit, int update) { - BMEditMesh *em; if ((scene->toolsettings->automerge) && (obedit && obedit->type == OB_MESH)) { - em = BMEdit_FromObject(obedit); - if (!em) + int ok; + BMEditMesh *em = BMEdit_FromObject(obedit); + + if (!em) { return; + } + + ok = BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, + "automerge verts=%hv dist=%f", + BM_ELEM_SELECT, scene->toolsettings->doublimit); - BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, - "automerge verts=%hv dist=%f", - BM_ELEM_SELECT, scene->toolsettings->doublimit); - if (update) { - DAG_id_tag_update(obedit->data, OB_RECALC_DATA); - BMEdit_RecalcTessellation(em); + if (LIKELY(ok) && update) { + EDBM_update_generic(em, true, true); } } } @@ -181,19 +184,19 @@ static void draw_triangulated(const int mcords[][2], const short tot) /* reads rect, and builds selection array for quick lookup */ /* returns if all is OK */ -int EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xmax, short ymax) +bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xmax, short ymax) { struct ImBuf *buf; unsigned int *dr; int a; if (vc->obedit == NULL || vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) { - return 0; + return false; } buf = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); - if (buf == NULL) return 0; - if (bm_vertoffs == 0) return 0; + if (buf == NULL) return false; + if (bm_vertoffs == 0) return false; dr = buf->rect; @@ -207,7 +210,7 @@ int EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xmax dr++; } IMB_freeImBuf(buf); - return 1; + return true; } int EDBM_backbuf_check(unsigned int index) @@ -230,7 +233,7 @@ void EDBM_backbuf_free(void) * - grab again and compare * returns 'OK' */ -int EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax) +bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax) { unsigned int *dr, *drm; struct ImBuf *buf, *bufmask; @@ -239,19 +242,22 @@ int EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short /* method in use for face selecting too */ if (vc->obedit == NULL) { if (!(paint_facesel_test(vc->obact) || paint_vertsel_test(vc->obact))) { - return 0; + return false; } } else if (vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) { - return 0; + return false; } buf = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); - if (buf == NULL) return 0; - if (bm_vertoffs == 0) return 0; + if (buf == NULL) return false; + if (bm_vertoffs == 0) return false; dr = buf->rect; + if (vc->rv3d->gpuoffscreen) + GPU_offscreen_bind(vc->rv3d->gpuoffscreen); + /* draw the mask */ glDisable(GL_DEPTH_TEST); @@ -269,11 +275,14 @@ int EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short glFinish(); /* to be sure readpixels sees mask */ + if (vc->rv3d->gpuoffscreen) + GPU_offscreen_unbind(vc->rv3d->gpuoffscreen); + /* grab mask */ bufmask = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); if (bufmask == NULL) { - return 0; /* only when mem alloc fails, go crash somewhere else! */ + return false; /* only when mem alloc fails, go crash somewhere else! */ } else { drm = bufmask->rect; @@ -290,11 +299,11 @@ int EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short IMB_freeImBuf(buf); IMB_freeImBuf(bufmask); - return 1; + return true; } /* circle shaped sample area */ -int EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) +bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) { struct ImBuf *buf; unsigned int *dr; @@ -304,16 +313,18 @@ int EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) /* method in use for face selecting too */ if (vc->obedit == NULL) { if (!(paint_facesel_test(vc->obact) || paint_vertsel_test(vc->obact))) { - return 0; + return false; } } - else if (vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) return 0; - + else if (vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) { + return false; + } + xmin = xs - rads; xmax = xs + rads; ymin = ys - rads; ymax = ys + rads; buf = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); - if (bm_vertoffs == 0) return 0; - if (buf == NULL) return 0; + if (bm_vertoffs == 0) return false; + if (buf == NULL) return false; dr = buf->rect; @@ -329,7 +340,7 @@ int EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) } IMB_freeImBuf(buf); - return 1; + return true; } @@ -385,7 +396,7 @@ static unsigned int findnearestvert__backbufIndextest(void *handle, unsigned int * if 0, unselected vertice are given the bias * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased */ -BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist, const short sel, const short strict) +BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist, const bool sel, const bool strict) { if (vc->v3d->drawtype > OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) { float distance; @@ -425,7 +436,7 @@ BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist, const short sel, data.lastIndex = lastSelectedIndex; data.mval_fl[0] = vc->mval[0]; data.mval_fl[1] = vc->mval[1]; - data.select = sel; + data.select = sel ? BM_ELEM_SELECT : 0; data.dist = *r_dist; data.strict = strict; data.closest = NULL; @@ -471,7 +482,7 @@ static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float vec[1] = eed->v1->co[1] + lambda * (eed->v2->co[1] - eed->v1->co[1]); vec[2] = eed->v1->co[2] + lambda * (eed->v2->co[2] - eed->v1->co[2]); - if (ED_view3d_clipping_test(data->vc.rv3d, vec, TRUE) == 0) { + if (ED_view3d_clipping_test(data->vc.rv3d, vec, true) == 0) { data->dist = distance; data->closest = eed; } @@ -681,6 +692,9 @@ static EnumPropertyItem prop_similar_types[] = { {SIMEDGE_BEVEL, "BEVEL", 0, "Bevel", ""}, {SIMEDGE_SEAM, "SEAM", 0, "Seam", ""}, {SIMEDGE_SHARP, "SHARP", 0, "Sharpness", ""}, +#ifdef WITH_FREESTYLE + {SIMEDGE_FREESTYLE, "FREESTYLE_EDGE", 0, "Freestyle Edge Marks", ""}, +#endif {SIMFACE_MATERIAL, "MATERIAL", 0, "Material", ""}, {SIMFACE_IMAGE, "IMAGE", 0, "Image", ""}, @@ -689,6 +703,9 @@ static EnumPropertyItem prop_similar_types[] = { {SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""}, {SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""}, {SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""}, +#ifdef WITH_FREESTYLE + {SIMFACE_FREESTYLE, "FREESTYLE_FACE", 0, "Freestyle Face Marks", ""}, +#endif {0, NULL, 0, NULL, NULL} }; @@ -718,14 +735,14 @@ static int similar_face_select_exec(bContext *C, wmOperator *op) EDBM_flag_disable_all(em, BM_ELEM_SELECT); /* select the output */ - BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true); /* finish the operator */ - if (!EDBM_op_finish(em, &bmop, op, TRUE)) { + if (!EDBM_op_finish(em, &bmop, op, true)) { return OPERATOR_CANCELLED; } - EDBM_update_generic(C, em, FALSE); + EDBM_update_generic(em, false, false); /* we succeeded */ return OPERATOR_FINISHED; @@ -759,15 +776,15 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op) EDBM_flag_disable_all(em, BM_ELEM_SELECT); /* select the output */ - BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true); EDBM_selectmode_flush(em); /* finish the operator */ - if (!EDBM_op_finish(em, &bmop, op, TRUE)) { + if (!EDBM_op_finish(em, &bmop, op, true)) { return OPERATOR_CANCELLED; } - EDBM_update_generic(C, em, FALSE); + EDBM_update_generic(em, false, false); /* we succeeded */ return OPERATOR_FINISHED; @@ -788,7 +805,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) BMOperator bmop; /* get the type from RNA */ const int type = RNA_enum_get(op->ptr, "type"); - float thresh = RNA_float_get(op->ptr, "threshold"); + const float thresh = RNA_float_get(op->ptr, "threshold"); const int compare = RNA_enum_get(op->ptr, "compare"); /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ @@ -803,16 +820,16 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) EDBM_flag_disable_all(em, BM_ELEM_SELECT); /* select the output */ - BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, true); /* finish the operator */ - if (!EDBM_op_finish(em, &bmop, op, TRUE)) { + if (!EDBM_op_finish(em, &bmop, op, true)) { return OPERATOR_CANCELLED; } EDBM_selectmode_flush(em); - EDBM_update_generic(C, em, FALSE); + EDBM_update_generic(em, false, false); /* we succeeded */ return OPERATOR_FINISHED; @@ -863,7 +880,11 @@ static EnumPropertyItem *select_similar_type_itemf(bContext *C, PointerRNA *UNUS } } else if (em->selectmode & SCE_SELECT_FACE) { +#ifdef WITH_FREESTYLE + for (a = SIMFACE_MATERIAL; a <= SIMFACE_FREESTYLE; a++) { +#else for (a = SIMFACE_MATERIAL; a <= SIMFACE_COPLANAR; a++) { +#endif RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a); } } @@ -908,10 +929,10 @@ void MESH_OT_select_similar(wmOperatorType *ot) static int edbm_select_mode_exec(bContext *C, wmOperator *op) { - const int type = RNA_enum_get(op->ptr, "type"); - const int action = RNA_enum_get(op->ptr, "action"); - const int use_extend = RNA_boolean_get(op->ptr, "use_extend"); - const int use_expand = RNA_boolean_get(op->ptr, "use_expand"); + const int type = RNA_enum_get(op->ptr, "type"); + const int action = RNA_enum_get(op->ptr, "action"); + const bool use_extend = RNA_boolean_get(op->ptr, "use_extend"); + const bool use_expand = RNA_boolean_get(op->ptr, "use_expand"); if (EDBM_selectmode_toggle(C, type, action, use_extend, use_expand)) { return OPERATOR_FINISHED; @@ -921,11 +942,15 @@ static int edbm_select_mode_exec(bContext *C, wmOperator *op) } } -static int edbm_select_mode_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int edbm_select_mode_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - // RNA_enum_set(op->ptr, "type"); /* type must be set already */ - RNA_boolean_set(op->ptr, "use_extend", event->shift); - RNA_boolean_set(op->ptr, "use_expand", event->ctrl); + /* detecting these options based on shift/ctrl here is weak, but it's done + * to make this work when clicking buttons or menus */ + if (!RNA_struct_property_is_set(op->ptr, "use_extend")) + RNA_boolean_set(op->ptr, "use_extend", event->shift); + if (!RNA_struct_property_is_set(op->ptr, "use_expand")) + RNA_boolean_set(op->ptr, "use_expand", event->ctrl); + return edbm_select_mode_exec(C, op); } @@ -961,9 +986,9 @@ void MESH_OT_select_mode(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - prop = RNA_def_boolean(ot->srna, "use_extend", FALSE, "Extend", ""); + prop = RNA_def_boolean(ot->srna, "use_extend", false, "Extend", ""); RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "use_expand", FALSE, "Expand", ""); + prop = RNA_def_boolean(ot->srna, "use_expand", false, "Expand", ""); RNA_def_property_flag(prop, PROP_SKIP_SAVE); ot->prop = prop = RNA_def_enum(ot->srna, "type", elem_items, 0, "Type", ""); RNA_def_property_flag(prop, PROP_SKIP_SAVE); @@ -975,7 +1000,7 @@ void MESH_OT_select_mode(wmOperatorType *ot) /* **************** LOOP SELECTS *************** */ -static void walker_select(BMEditMesh *em, int walkercode, void *start, int select) +static void walker_select(BMEditMesh *em, int walkercode, void *start, const bool select) { BMesh *bm = em->bm; BMElem *ele; @@ -985,8 +1010,8 @@ static void walker_select(BMEditMesh *em, int walkercode, void *start, int selec BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP, BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - ele = BMW_begin(&walker, start); - for (; ele; ele = BMW_step(&walker)) { + + for (ele = BMW_begin(&walker, start); ele; ele = BMW_step(&walker)) { if (!select) { BM_select_history_remove(bm, ele); } @@ -1002,7 +1027,7 @@ static int edbm_loop_multiselect_exec(bContext *C, wmOperator *op) BMEdge *eed; BMEdge **edarray; int edindex; - int looptype = RNA_boolean_get(op->ptr, "ring"); + const bool is_ring = RNA_boolean_get(op->ptr, "ring"); BMIter iter; int totedgesel = 0; @@ -1023,17 +1048,17 @@ static int edbm_loop_multiselect_exec(bContext *C, wmOperator *op) } } - if (looptype) { + if (is_ring) { for (edindex = 0; edindex < totedgesel; edindex += 1) { eed = edarray[edindex]; - walker_select(em, BMW_EDGERING, eed, TRUE); + walker_select(em, BMW_EDGERING, eed, true); } EDBM_selectmode_flush(em); } else { for (edindex = 0; edindex < totedgesel; edindex += 1) { eed = edarray[edindex]; - walker_select(em, BMW_LOOP, eed, TRUE); + walker_select(em, BMW_LOOP, eed, true); } EDBM_selectmode_flush(em); } @@ -1069,12 +1094,12 @@ void MESH_OT_loop_multi_select(wmOperatorType *ot) /* ***************** loop select (non modal) ************** */ -static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short deselect, short toggle, short ring) +static void mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, bool ring) { ViewContext vc; BMEditMesh *em; BMEdge *eed; - int select = TRUE; + bool select = true; float dist = 50.0f; float mvalf[2]; @@ -1088,21 +1113,21 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short desele eed = EDBM_edge_find_nearest(&vc, &dist); if (eed) { - if (extend == 0 && deselect == 0 && toggle == 0) { + if (extend == false && deselect == false && toggle == false) { EDBM_flag_disable_all(em, BM_ELEM_SELECT); } if (extend) { - select = TRUE; + select = true; } else if (deselect) { - select = FALSE; + select = false; } else if (BM_elem_flag_test(eed, BM_ELEM_SELECT) == 0) { - select = TRUE; + select = true; } else if (toggle) { - select = FALSE; + select = false; } if (em->selectmode & SCE_SELECT_FACE) { @@ -1136,11 +1161,11 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short desele /* We can't be sure this has already been set... */ ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); - if (ED_view3d_project_float_object(vc.ar, eed->v1->co, v1_co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + if (ED_view3d_project_float_object(vc.ar, eed->v1->co, v1_co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) { length_1 = len_squared_v2v2(mvalf, v1_co); } - if (ED_view3d_project_float_object(vc.ar, eed->v2->co, v2_co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + if (ED_view3d_project_float_object(vc.ar, eed->v2->co, v2_co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) { length_2 = len_squared_v2v2(mvalf, v2_co); } #if 0 @@ -1156,7 +1181,7 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short desele /* Select the face of eed which is the nearest of mouse. */ BMFace *f, *efa = NULL; BMIter iterf; - float best_dist = MAXFLOAT; + float best_dist = FLT_MAX; /* We can't be sure this has already been set... */ ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); @@ -1167,7 +1192,7 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short desele float co[2], tdist; BM_face_calc_center_mean(f, cent); - if (ED_view3d_project_float_object(vc.ar, cent, co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + if (ED_view3d_project_float_object(vc.ar, cent, co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) { tdist = len_squared_v2v2(mvalf, co); if (tdist < best_dist) { /* printf("Best face: %p (%f)\n", f, tdist);*/ @@ -1188,12 +1213,13 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short desele } } -static int edbm_select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int edbm_select_loop_invoke(bContext *C, wmOperator *op, const wmEvent *event) { view3d_operator_needs_opengl(C); - mouse_mesh_loop(C, event->mval, RNA_boolean_get(op->ptr, "extend"), + mouse_mesh_loop(C, event->mval, + RNA_boolean_get(op->ptr, "extend"), RNA_boolean_get(op->ptr, "deselect"), RNA_boolean_get(op->ptr, "toggle"), RNA_boolean_get(op->ptr, "ring")); @@ -1319,6 +1345,23 @@ static void edgetag_context_set(BMesh *bm, Scene *scene, BMEdge *e, int val) case EDGE_MODE_TAG_BEVEL: BM_elem_float_data_set(&bm->edata, e, CD_BWEIGHT, (val) ? 1.0f : 0.0f); break; +#ifdef WITH_FREESTYLE + case EDGE_MODE_TAG_FREESTYLE: + { + FreestyleEdge *fed; + + if (!CustomData_has_layer(&bm->pdata, CD_FREESTYLE_FACE)) { + BM_data_layer_add(bm, &bm->pdata, CD_FREESTYLE_FACE); + } + + fed = CustomData_bmesh_get(&bm->edata, e->head.data, CD_FREESTYLE_EDGE); + if (!val) + fed->flag &= ~FREESTYLE_EDGE_MARK; + else + fed->flag |= FREESTYLE_EDGE_MARK; + } + break; +#endif } } @@ -1326,19 +1369,43 @@ static int edgetag_context_check(Scene *scene, BMesh *bm, BMEdge *e) { switch (scene->toolsettings->edge_mode) { case EDGE_MODE_SELECT: - return BM_elem_flag_test(e, BM_ELEM_SELECT) ? TRUE : FALSE; + return BM_elem_flag_test(e, BM_ELEM_SELECT) ? true : false; case EDGE_MODE_TAG_SEAM: return BM_elem_flag_test(e, BM_ELEM_SEAM); case EDGE_MODE_TAG_SHARP: return !BM_elem_flag_test(e, BM_ELEM_SMOOTH); case EDGE_MODE_TAG_CREASE: - return BM_elem_float_data_get(&bm->edata, e, CD_CREASE) ? TRUE : FALSE; + return BM_elem_float_data_get(&bm->edata, e, CD_CREASE) ? true : false; case EDGE_MODE_TAG_BEVEL: - return BM_elem_float_data_get(&bm->edata, e, CD_BWEIGHT) ? TRUE : FALSE; + return BM_elem_float_data_get(&bm->edata, e, CD_BWEIGHT) ? true : false; +#ifdef WITH_FREESTYLE + case EDGE_MODE_TAG_FREESTYLE: + { + FreestyleEdge *fed = CustomData_bmesh_get(&bm->edata, e->head.data, CD_FREESTYLE_EDGE); + return (!fed) ? FALSE : (fed->flag & FREESTYLE_EDGE_MARK) ? TRUE : FALSE; + } + break; +#endif } return 0; } +static void edgetag_ensure_cd_flag(Scene *scene, Mesh *me) +{ + BMesh *bm = me->edit_btmesh->bm; + + switch (scene->toolsettings->edge_mode) { + case EDGE_MODE_TAG_CREASE: + BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_CREASE); + break; + case EDGE_MODE_TAG_BEVEL: + BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_BWEIGHT); + break; + default: + break; + } +} + static int edgetag_shortest_path(Scene *scene, BMesh *bm, BMEdge *e_src, BMEdge *e_dst) { /* BM_ELEM_TAG flag is used to store visited edges */ @@ -1352,8 +1419,10 @@ static int edgetag_shortest_path(Scene *scene, BMesh *bm, BMEdge *e_src, BMEdge /* note, would pass BM_EDGE except we are looping over all edges anyway */ BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */); + edgetag_ensure_cd_flag(scene, OBACT->data); + BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, i) { - if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == FALSE) { + if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) { BM_elem_flag_disable(e, BM_ELEM_TAG); } else { @@ -1402,14 +1471,14 @@ static int edgetag_shortest_path(Scene *scene, BMesh *bm, BMEdge *e_src, BMEdge } if (e == e_dst) { - short all_set = TRUE; + bool all_set = true; /* Check whether the path is already completely tagged. * if it is, the tags will be cleared instead of set. */ e = e_dst; do { if (!edgetag_context_check(scene, bm, e)) { - all_set = FALSE; + all_set = false; break; } } while ((e = edges_prev[BM_elem_index_get(e)])); @@ -1431,7 +1500,7 @@ static int edgetag_shortest_path(Scene *scene, BMesh *bm, BMEdge *e_src, BMEdge /* ******************* mesh shortest path select, uses prev-selected edge ****************** */ /* since you want to create paths with multiple selects, it doesn't have extend option */ -static int mouse_mesh_shortest_path_edge(bContext *C, ViewContext *vc) +static int mouse_mesh_shortest_path_edge(ViewContext *vc) { BMEditMesh *em = vc->em; BMEdge *e_dst; @@ -1440,7 +1509,7 @@ static int mouse_mesh_shortest_path_edge(bContext *C, ViewContext *vc) e_dst = EDBM_edge_find_nearest(vc, &dist); if (e_dst) { Mesh *me = vc->obedit->data; - int path = 0; + bool is_path = false; if (em->bm->selected.last) { BMEditSelection *ese = em->bm->selected.last; @@ -1451,13 +1520,14 @@ static int mouse_mesh_shortest_path_edge(bContext *C, ViewContext *vc) if (e_act != e_dst) { if (edgetag_shortest_path(vc->scene, em->bm, e_act, e_dst)) { BM_select_history_remove(em->bm, e_act); - path = 1; + is_path = true; } } } } - if (path == 0) { + if (is_path == false) { int act = (edgetag_context_check(vc->scene, em->bm, e_dst) == 0); + edgetag_ensure_cd_flag(vc->scene, vc->obedit->data); edgetag_context_set(em->bm, vc->scene, e_dst, act); /* switch the edge option */ } @@ -1470,7 +1540,7 @@ static int mouse_mesh_shortest_path_edge(bContext *C, ViewContext *vc) BM_select_history_store(em->bm, e_dst); /* force drawmode for mesh */ - switch (CTX_data_tool_settings(C)->edge_mode) { + switch (vc->scene->toolsettings->edge_mode) { case EDGE_MODE_TAG_SEAM: me->drawflag |= ME_DRAWSEAMS; @@ -1485,14 +1555,19 @@ static int mouse_mesh_shortest_path_edge(bContext *C, ViewContext *vc) case EDGE_MODE_TAG_BEVEL: me->drawflag |= ME_DRAWBWEIGHTS; break; +#ifdef WITH_FREESTYLE + case EDGE_MODE_TAG_FREESTYLE: + me->drawflag |= ME_DRAW_FREESTYLE_EDGE; + break; +#endif } - EDBM_update_generic(C, em, FALSE); + EDBM_update_generic(em, false, false); - return TRUE; + return true; } else { - return FALSE; + return false; } } @@ -1569,7 +1644,7 @@ static int facetag_shortest_path(Scene *scene, BMesh *bm, BMFace *f_src, BMFace // BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */); // NOT NEEDED FOR FACETAG BM_ITER_MESH_INDEX (f, &fiter, bm, BM_FACES_OF_MESH, i) { - if (BM_elem_flag_test(f, BM_ELEM_HIDDEN) == FALSE) { + if (BM_elem_flag_test(f, BM_ELEM_HIDDEN) == false) { BM_elem_flag_disable(f, BM_ELEM_TAG); } else { @@ -1618,14 +1693,14 @@ static int facetag_shortest_path(Scene *scene, BMesh *bm, BMFace *f_src, BMFace } if (f == f_dst) { - short all_set = TRUE; + bool all_set = true; /* Check whether the path is already completely tagged. * if it is, the tags will be cleared instead of set. */ f = f_dst; do { if (!facetag_context_check(scene, bm, f)) { - all_set = FALSE; + all_set = false; break; } } while ((f = faces_prev[BM_elem_index_get(f)])); @@ -1644,7 +1719,7 @@ static int facetag_shortest_path(Scene *scene, BMesh *bm, BMFace *f_src, BMFace return 1; } -static int mouse_mesh_shortest_path_face(bContext *C, ViewContext *vc) +static int mouse_mesh_shortest_path_face(ViewContext *vc) { BMEditMesh *em = vc->em; BMFace *f_dst; @@ -1653,7 +1728,7 @@ static int mouse_mesh_shortest_path_face(bContext *C, ViewContext *vc) f_dst = EDBM_face_find_nearest(vc, &dist); if (f_dst) { int path = 0; - BMFace *f_act = BM_active_face_get(em->bm, FALSE, TRUE); + BMFace *f_act = BM_active_face_get(em->bm, false, true); if (f_act) { if (f_act != f_dst) { @@ -1678,19 +1753,19 @@ static int mouse_mesh_shortest_path_face(bContext *C, ViewContext *vc) BM_active_face_set(em->bm, f_dst); - EDBM_update_generic(C, em, FALSE); + EDBM_update_generic(em, false, false); - return TRUE; + return true; } else { - return FALSE; + return false; } } /* ******************* operator for edge and face tag ****************** */ -static int edbm_shortest_path_select_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int edbm_shortest_path_select_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { ViewContext vc; BMEditMesh *em; @@ -1703,7 +1778,7 @@ static int edbm_shortest_path_select_invoke(bContext *C, wmOperator *UNUSED(op), em = vc.em; if (em->selectmode & SCE_SELECT_EDGE) { - if (mouse_mesh_shortest_path_edge(C, &vc)) { + if (mouse_mesh_shortest_path_edge(&vc)) { return OPERATOR_FINISHED; } else { @@ -1711,7 +1786,7 @@ static int edbm_shortest_path_select_invoke(bContext *C, wmOperator *UNUSED(op), } } else if (em->selectmode & SCE_SELECT_FACE) { - if (mouse_mesh_shortest_path_face(C, &vc)) { + if (mouse_mesh_shortest_path_face(&vc)) { return OPERATOR_FINISHED; } else { @@ -1747,13 +1822,13 @@ void MESH_OT_select_shortest_path(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); } /* ************************************************** */ /* here actual select happens */ /* gets called via generic mouse select operator */ -int EDBM_select_pick(bContext *C, const int mval[2], short extend, short deselect, short toggle) +bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle) { ViewContext vc; BMVert *eve = NULL; @@ -1768,7 +1843,7 @@ int EDBM_select_pick(bContext *C, const int mval[2], short extend, short deselec if (unified_findnearest(&vc, &eve, &eed, &efa)) { /* Deselect everything */ - if (extend == 0 && deselect == 0 && toggle == 0) + if (extend == false && deselect == false && toggle == false) EDBM_flag_disable_all(vc.em, BM_ELEM_SELECT); if (efa) { @@ -1779,13 +1854,13 @@ int EDBM_select_pick(bContext *C, const int mval[2], short extend, short deselec /* 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_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); + BM_face_select_set(vc.em->bm, efa, true); } else if (deselect) { BM_select_history_remove(vc.em->bm, efa); - BM_face_select_set(vc.em->bm, efa, FALSE); + BM_face_select_set(vc.em->bm, efa, false); } else { /* set the last selected face */ @@ -1793,11 +1868,11 @@ int EDBM_select_pick(bContext *C, const int mval[2], short extend, short deselec 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); + BM_face_select_set(vc.em->bm, efa, true); } else if (toggle) { BM_select_history_remove(vc.em->bm, efa); - BM_face_select_set(vc.em->bm, efa, FALSE); + BM_face_select_set(vc.em->bm, efa, false); } } } @@ -1806,22 +1881,22 @@ int EDBM_select_pick(bContext *C, const int mval[2], short extend, short deselec /* 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_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); + BM_edge_select_set(vc.em->bm, eed, true); } else if (deselect) { BM_select_history_remove(vc.em->bm, eed); - BM_edge_select_set(vc.em->bm, eed, FALSE); + 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); + 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); + BM_edge_select_set(vc.em->bm, eed, false); } } } @@ -1830,22 +1905,22 @@ int EDBM_select_pick(bContext *C, const int mval[2], short extend, short deselec /* 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_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); + BM_vert_select_set(vc.em->bm, eve, true); } else if (deselect) { BM_select_history_remove(vc.em->bm, eve); - BM_vert_select_set(vc.em->bm, eve, FALSE); + 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); + 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); + BM_vert_select_set(vc.em->bm, eve, false); } } } @@ -1862,10 +1937,10 @@ int EDBM_select_pick(bContext *C, const int mval[2], short extend, short deselec } WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit); - return 1; + return true; } - return 0; + return false; } static void edbm_strip_selections(BMEditMesh *em) @@ -1911,38 +1986,57 @@ void EDBM_selectmode_set(BMEditMesh *em) edbm_strip_selections(em); /* strip BMEditSelections from em->selected that are not relevant to new mode */ + if (em->bm->totvertsel == 0 && + em->bm->totedgesel == 0 && + em->bm->totfacesel == 0) + { + return; + } + if (em->selectmode & SCE_SELECT_VERTEX) { - EDBM_select_flush(em); + if (em->bm->totvertsel) { + EDBM_select_flush(em); + } } else if (em->selectmode & SCE_SELECT_EDGE) { /* deselect vertices, and select again based on edge select */ - eve = BM_iter_new(&iter, em->bm, BM_VERTS_OF_MESH, NULL); - for (; eve; eve = BM_iter_step(&iter)) BM_vert_select_set(em->bm, eve, FALSE); - - eed = BM_iter_new(&iter, em->bm, BM_EDGES_OF_MESH, NULL); - for (; eed; eed = BM_iter_step(&iter)) { - if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) { - BM_edge_select_set(em->bm, eed, TRUE); + BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { + BM_vert_select_set(em->bm, eve, false); + } + + if (em->bm->totedgesel) { + BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) { + BM_edge_select_set(em->bm, eed, true); + } } + + /* selects faces based on edge status */ + EDBM_selectmode_flush(em); } - - /* selects faces based on edge status */ - EDBM_selectmode_flush(em); } else if (em->selectmode & SCE_SELECT_FACE) { /* deselect eges, and select again based on face select */ - eed = BM_iter_new(&iter, em->bm, BM_EDGES_OF_MESH, NULL); - for (; eed; eed = BM_iter_step(&iter)) BM_edge_select_set(em->bm, eed, FALSE); - - efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL); - for (; efa; efa = BM_iter_step(&iter)) { - if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { - BM_face_select_set(em->bm, efa, TRUE); + BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { + BM_edge_select_set(em->bm, eed, false); + } + + if (em->bm->totfacesel) { + efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL); + for (; efa; efa = BM_iter_step(&iter)) { + if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { + BM_face_select_set(em->bm, efa, true); + } } } } } +/** + * Flush the selection up: + * - vert -> edge + * - edge -> face + */ void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const short selectmode_new) { BMEdge *eed; @@ -1953,7 +2047,10 @@ void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const s /* have to find out what the selectionmode was previously */ if (selectmode_old == SCE_SELECT_VERTEX) { - if (selectmode_new == SCE_SELECT_EDGE) { + if (em->bm->totvertsel == 0) { + /* pass */ + } + else if (selectmode_new == SCE_SELECT_EDGE) { /* select all edges associated with every selected vert */ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { BM_elem_flag_set(eed, BM_ELEM_TAG, BM_edge_is_any_vert_flag_test(eed, BM_ELEM_SELECT)); @@ -1961,7 +2058,7 @@ void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const s BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(eed, BM_ELEM_TAG)) { - BM_edge_select_set(em->bm, eed, TRUE); + BM_edge_select_set(em->bm, eed, true); } } } @@ -1973,13 +2070,16 @@ void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const s BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - BM_face_select_set(em->bm, efa, TRUE); + BM_face_select_set(em->bm, efa, true); } } } } else if (selectmode_old == SCE_SELECT_EDGE) { - if (selectmode_new == SCE_SELECT_FACE) { + if (em->bm->totedgesel == 0) { + /* pass */ + } + else if (selectmode_new == SCE_SELECT_FACE) { /* select all faces associated with every selected edge */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_edge_flag_test(efa, BM_ELEM_SELECT)); @@ -1987,7 +2087,7 @@ void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const s BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - BM_face_select_set(em->bm, efa, TRUE); + BM_face_select_set(em->bm, efa, true); } } } @@ -1995,13 +2095,13 @@ void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const s } /* user facing function, does notification and undo push */ -int EDBM_selectmode_toggle(bContext *C, const short selectmode_new, - const int action, const int use_extend, const int use_expand) +bool EDBM_selectmode_toggle(bContext *C, const short selectmode_new, + const int action, const bool use_extend, const bool use_expand) { ToolSettings *ts = CTX_data_tool_settings(C); Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = NULL; - int ret = FALSE; + bool ret = false; if (obedit && obedit->type == OB_MESH) { em = BMEdit_FromObject(obedit); @@ -2018,21 +2118,21 @@ int EDBM_selectmode_toggle(bContext *C, const short selectmode_new, case 0: /* disable */ /* check we have something to do */ if ((em->selectmode & selectmode_new) == 0) { - return FALSE; + return false; } em->selectmode &= ~selectmode_new; break; case 1: /* enable */ /* check we have something to do */ if ((em->selectmode & selectmode_new) != 0) { - return FALSE; + return false; } em->selectmode |= selectmode_new; break; case 2: /* toggle */ /* can't disable this flag if its the only one set */ if (em->selectmode == selectmode_new) { - return FALSE; + return false; } em->selectmode ^= selectmode_new; break; @@ -2046,7 +2146,7 @@ int EDBM_selectmode_toggle(bContext *C, const short selectmode_new, em->selectmode = SCE_SELECT_VERTEX; ts->selectmode = em->selectmode; EDBM_selectmode_set(em); - ret = TRUE; + ret = true; break; case SCE_SELECT_EDGE: if (use_extend == 0 || em->selectmode == 0) { @@ -2060,7 +2160,7 @@ int EDBM_selectmode_toggle(bContext *C, const short selectmode_new, } ts->selectmode = em->selectmode; EDBM_selectmode_set(em); - ret = TRUE; + ret = true; break; case SCE_SELECT_FACE: if (use_extend == 0 || em->selectmode == 0) { @@ -2075,14 +2175,14 @@ int EDBM_selectmode_toggle(bContext *C, const short selectmode_new, } ts->selectmode = em->selectmode; EDBM_selectmode_set(em); - ret = TRUE; + ret = true; break; default: BLI_assert(0); break; } - if (ret == TRUE) { + if (ret == true) { WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL); } @@ -2090,6 +2190,37 @@ int EDBM_selectmode_toggle(bContext *C, const short selectmode_new, return ret; } +/** + * Use to disable a selectmode if its enabled, Using another mode as a fallback + * if the disabled mode is the only mode set. + * + * \return true if the mode is changed. + */ +bool EDBM_selectmode_disable(Scene *scene, BMEditMesh *em, + const short selectmode_disable, + const short selectmode_fallback) +{ + /* note essential, but switch out of vertex mode since the + * selected regions wont be nicely isolated after flushing */ + if (em->selectmode & selectmode_disable) { + if (em->selectmode == selectmode_disable) { + em->selectmode = selectmode_fallback; + } + else { + em->selectmode &= ~selectmode_disable; + } + scene->toolsettings->selectmode = em->selectmode; + EDBM_selectmode_set(em); + + WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, scene); + + return true; + } + else { + return false; + } +} + void EDBM_deselect_by_material(BMEditMesh *em, const short index, const short select) { BMIter iter; @@ -2151,25 +2282,25 @@ int EDBM_select_interior_faces(BMEditMesh *em) BMIter eiter; BMFace *efa; BMEdge *eed; - int ok; - int change = FALSE; + bool ok; + bool change = false; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) continue; - ok = TRUE; + ok = true; BM_ITER_ELEM (eed, &eiter, efa, BM_EDGES_OF_FACE) { if (BM_edge_face_count(eed) < 3) { - ok = FALSE; + ok = false; break; } } if (ok) { - BM_face_select_set(bm, efa, TRUE); - change = TRUE; + BM_face_select_set(bm, efa, true); + change = true; } } @@ -2182,13 +2313,13 @@ static void linked_limit_default(bContext *C, wmOperator *op) Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); if (em->selectmode == SCE_SELECT_FACE) - RNA_boolean_set(op->ptr, "limit", TRUE); + RNA_boolean_set(op->ptr, "limit", true); else - RNA_boolean_set(op->ptr, "limit", FALSE); + RNA_boolean_set(op->ptr, "limit", false); } } -static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Object *obedit = CTX_data_edit_object(C); ViewContext vc; @@ -2251,8 +2382,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent * BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - e = BMW_begin(&walker, efa); - for (; efa; efa = BMW_step(&walker)) { + for (efa = BMW_begin(&walker, efa); efa; efa = BMW_step(&walker)) { BM_face_select_set(bm, efa, sel); } BMW_end(&walker); @@ -2273,8 +2403,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent * BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - e = BMW_begin(&walker, eed->v1); - for (; e; e = BMW_step(&walker)) { + for (e = BMW_begin(&walker, eed->v1); e; e = BMW_step(&walker)) { BM_edge_select_set(bm, e, sel); } BMW_end(&walker); @@ -2345,9 +2474,8 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - e = BMW_begin(&walker, efa); - for (; efa; efa = BMW_step(&walker)) { - BM_face_select_set(bm, efa, TRUE); + for (efa = BMW_begin(&walker, efa); efa; efa = BMW_step(&walker)) { + BM_face_select_set(bm, efa, true); } } } @@ -2374,16 +2502,15 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_TAG)) { - e = BMW_begin(&walker, v); - for (; e; e = BMW_step(&walker)) { - BM_vert_select_set(em->bm, e->v1, TRUE); - BM_vert_select_set(em->bm, e->v2, TRUE); + for (e = BMW_begin(&walker, v); e; e = BMW_step(&walker)) { + BM_edge_select_set(em->bm, e, true); } } } BMW_end(&walker); + + EDBM_selectmode_flush(em); } - EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit); @@ -2530,7 +2657,7 @@ static void walker_deselect_nth(BMEditMesh *em, int nth, int offset, BMHeader *h if (!BM_elem_flag_test(ele, BM_ELEM_TAG)) { /* Deselect elements that aren't at "nth" depth from active */ if ((offset + BMW_current_depth(&walker)) % nth) { - BM_elem_select_set(bm, ele, FALSE); + BM_elem_select_set(bm, ele, false); } BM_elem_flag_enable(ele, BM_ELEM_TAG); } @@ -2589,7 +2716,7 @@ static void deselect_nth_active(BMEditMesh *em, BMVert **r_eve, BMEdge **r_eed, } } else if (em->selectmode & SCE_SELECT_FACE) { - f = BM_active_face_get(em->bm, TRUE, FALSE); + f = BM_active_face_get(em->bm, true, false); if (f) { *r_efa = f; return; @@ -2625,17 +2752,18 @@ static int edbm_select_nth_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); - int nth = RNA_int_get(op->ptr, "nth"); + const int nth = RNA_int_get(op->ptr, "nth"); int offset = RNA_int_get(op->ptr, "offset"); - offset = MIN2(nth, offset); + /* so input of offset zero ends up being (nth - 1) */ + offset = (offset + (nth - 1)) % nth; if (edbm_deselect_nth(em, nth, offset) == 0) { BKE_report(op->reports, RPT_ERROR, "Mesh has no active vert/edge/face"); return OPERATOR_CANCELLED; } - EDBM_update_generic(C, em, FALSE); + EDBM_update_generic(em, false, false); return OPERATOR_FINISHED; } @@ -2646,7 +2774,7 @@ void MESH_OT_select_nth(wmOperatorType *ot) /* identifiers */ ot->name = "Checker Deselect"; ot->idname = "MESH_OT_select_nth"; - ot->description = "Deselect every Nth element starting from a selected vertex, edge or face"; + ot->description = "Deselect every Nth element starting from the active vertex, edge or face"; /* api callbacks */ ot->exec = edbm_select_nth_exec; @@ -2692,14 +2820,14 @@ static int edbm_select_sharp_edges_exec(bContext *C, wmOperator *op) const float sharp = RNA_float_get(op->ptr, "sharpness"); BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == FALSE && + if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false && BM_edge_loop_pair(e, &l1, &l2)) { /* edge has exactly two neighboring faces, check angle */ const float angle = angle_normalized_v3v3(l1->f->no, l2->f->no); if (fabsf(angle) > sharp) { - BM_edge_select_set(em->bm, e, TRUE); + BM_edge_select_set(em->bm, e, true); } } } @@ -2739,7 +2867,7 @@ static int edbm_select_linked_flat_faces_exec(bContext *C, wmOperator *op) BMFace *f, **stack = NULL; BLI_array_declare(stack); BMLoop *l, *l2; - float sharp = RNA_float_get(op->ptr, "sharpness"); + const float sharp = RNA_float_get(op->ptr, "sharpness"); int i; BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) { @@ -2760,7 +2888,7 @@ static int edbm_select_linked_flat_faces_exec(bContext *C, wmOperator *op) f = stack[i - 1]; i--; - BM_face_select_set(em->bm, f, TRUE); + BM_face_select_set(em->bm, f, true); BM_elem_flag_enable(f, BM_ELEM_TAG); @@ -2822,6 +2950,9 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op) BMEdge *e; BMIter iter; + if (!RNA_boolean_get(op->ptr, "extend")) + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + /* Selects isolated verts, and edges that do not have 2 neighboring * faces */ @@ -2833,13 +2964,13 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op) BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) { if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN) && !BM_vert_is_manifold(v)) { - BM_vert_select_set(em->bm, v, TRUE); + BM_vert_select_set(em->bm, v, true); } } BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN) && !BM_edge_is_manifold(e)) { - BM_edge_select_set(em->bm, e, TRUE); + BM_edge_select_set(em->bm, e, true); } } @@ -2861,6 +2992,9 @@ void MESH_OT_select_non_manifold(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* props */ + RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend the selection"); } static int edbm_select_random_exec(bContext *C, wmOperator *op) @@ -2871,7 +3005,7 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op) BMEdge *eed; BMFace *efa; BMIter iter; - float randfac = RNA_float_get(op->ptr, "percent") / 100.0f; + const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f; BLI_srand(BLI_rand()); /* random seed */ @@ -2881,7 +3015,7 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op) if (em->selectmode & SCE_SELECT_VERTEX) { BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BLI_frand() < randfac) { - BM_vert_select_set(em->bm, eve, TRUE); + BM_vert_select_set(em->bm, eve, true); } } EDBM_selectmode_flush(em); @@ -2889,7 +3023,7 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op) else if (em->selectmode & SCE_SELECT_EDGE) { BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BLI_frand() < randfac) { - BM_edge_select_set(em->bm, eed, TRUE); + BM_edge_select_set(em->bm, eed, true); } } EDBM_selectmode_flush(em); @@ -2897,7 +3031,7 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op) else { BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BLI_frand() < randfac) { - BM_face_select_set(em->bm, efa, TRUE); + BM_face_select_set(em->bm, efa, true); } } EDBM_selectmode_flush(em); @@ -2925,8 +3059,60 @@ void MESH_OT_select_random(wmOperatorType *ot) /* props */ RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f, "Percent", "Percentage of elements to select randomly", 0.f, 100.0f); - RNA_def_boolean(ot->srna, "extend", 0, - "Extend Selection", "Extend selection instead of deselecting everything first"); + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); +} + +static int edbm_select_ungrouped_exec(bContext *C, wmOperator *op) +{ + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BMEdit_FromObject(obedit); + BMVert *eve; + BMIter iter; + + if ((em->selectmode & SCE_SELECT_VERTEX) == 0) { + BKE_report(op->reports, RPT_ERROR, "Does not work out of vertex selection mode"); + return OPERATOR_CANCELLED; + } + + if (obedit->defbase.first == NULL) { + BKE_report(op->reports, RPT_ERROR, "No weights/vertex groups on object"); + return OPERATOR_CANCELLED; + } + + if (!RNA_boolean_get(op->ptr, "extend")) { + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + } + + BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { + if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { + MDeformVert *dv = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT); + /* no dv or dv set with no weight */ + if (dv == NULL || (dv && dv->dw == NULL)) { + BM_vert_select_set(em->bm, eve, true); + } + } + } + + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_select_ungrouped(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Ungrouped"; + ot->idname = "MESH_OT_select_ungrouped"; + ot->description = "Select vertices without a group"; + + /* api callbacks */ + ot->exec = edbm_select_ungrouped_exec; + ot->poll = ED_operator_editmesh; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); } static int edbm_select_next_loop_exec(bContext *C, wmOperator *UNUSED(op)) @@ -2948,14 +3134,14 @@ static int edbm_select_next_loop_exec(bContext *C, wmOperator *UNUSED(op)) BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { if (BM_elem_flag_test(l->v, BM_ELEM_SELECT)) { BM_elem_flag_enable(l->next->v, BM_ELEM_TAG); - BM_vert_select_set(em->bm, l->v, FALSE); + BM_vert_select_set(em->bm, l->v, false); } } } BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_TAG)) { - BM_vert_select_set(em->bm, v, TRUE); + BM_vert_select_set(em->bm, v, true); } } @@ -2987,7 +3173,7 @@ static int edbm_region_to_loop_exec(bContext *C, wmOperator *UNUSED(op)) BMEdge *e; BMIter iter; - BM_mesh_elem_hflag_disable_all(em->bm, BM_EDGE, BM_ELEM_TAG, FALSE); + BM_mesh_elem_hflag_disable_all(em->bm, BM_EDGE, BM_ELEM_TAG, false); BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) { BMLoop *l1, *l2; @@ -3010,7 +3196,7 @@ static int edbm_region_to_loop_exec(bContext *C, wmOperator *UNUSED(op)) BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_TAG)) { - BM_edge_select_set(em->bm, e, TRUE); + BM_edge_select_set(em->bm, e, true); } } @@ -3186,22 +3372,22 @@ static int edbm_loop_to_region_exec(bContext *C, wmOperator *op) BMEditMesh *em = BMEdit_FromObject(obedit); BMIter iter; BMFace *f; - int selbigger = RNA_boolean_get(op->ptr, "select_bigger"); + const bool select_bigger = RNA_boolean_get(op->ptr, "select_bigger"); int a, b; /* find the set of regions with smallest number of total faces */ - a = loop_find_regions(em, selbigger); - b = loop_find_regions(em, !selbigger); + a = loop_find_regions(em, select_bigger); + b = loop_find_regions(em, !select_bigger); - if ((a <= b) ^ selbigger) { - loop_find_regions(em, selbigger); + if ((a <= b) ^ select_bigger) { + loop_find_regions(em, select_bigger); } EDBM_flag_disable_all(em, BM_ELEM_SELECT); BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(f, BM_ELEM_TAG) && !BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - BM_face_select_set(em->bm, f, TRUE); + BM_face_select_set(em->bm, f, true); } } |