From add5dd3797bb09be76e3a1ff04a9f641d1ef23e9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 13 Nov 2012 05:44:49 +0000 Subject: add an operator for mesh mode switching, this lets python menu for mode setting do mixed selection and extending the selection - just like the buttons in the header. --- source/blender/editors/include/ED_mesh.h | 5 + source/blender/editors/mesh/editmesh_select.c | 165 +++++++++++++++++++++ source/blender/editors/mesh/mesh_intern.h | 1 + source/blender/editors/mesh/mesh_ops.c | 1 + .../blender/editors/space_view3d/view3d_header.c | 45 +----- 5 files changed, 176 insertions(+), 41 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 5ffcfbd94f0..865da8f0e6e 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -153,6 +153,11 @@ int EDBM_select_pick(struct bContext *C, const int mval[2], short extend, short void EDBM_selectmode_set(struct BMEditMesh *em); void EDBM_selectmode_convert(struct BMEditMesh *em, const short selectmode_old, const short selectmode_new); +/* user access this */ +int EDBM_selectmode_toggle(struct bContext *C, const short selectmode_new, + const int action, const int use_extend, const int use_expand); + + void EDBM_deselect_by_material(struct BMEditMesh *em, const short index, const short select); void EDBM_select_toggle_all(struct BMEditMesh *em); diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 2acbbb6e006..5be03c50240 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -56,6 +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" @@ -68,6 +69,7 @@ #include "mesh_intern.h" +#include "UI_resources.h" /* ****************************** MIRROR **************** */ @@ -915,6 +917,74 @@ void MESH_OT_select_similar(wmOperatorType *ot) RNA_def_float(ot->srna, "threshold", 0.0, 0.0, 1.0, "Threshold", "", 0.0, 1.0); } + +/* **************** Mode Select *************** */ + +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"); + + if (EDBM_selectmode_toggle(C, type, action, use_extend, use_expand)) { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +static int edbm_select_mode_invoke(bContext *C, wmOperator *op, 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); + return edbm_select_mode_exec(C, op); +} + +void MESH_OT_select_mode(wmOperatorType *ot) +{ + PropertyRNA *prop; + + static EnumPropertyItem elem_items[] = { + {SCE_SELECT_VERTEX, "VERT", ICON_VERTEXSEL, "Vertices", ""}, + {SCE_SELECT_EDGE, "EDGE", ICON_EDGESEL, "Edges", ""}, + {SCE_SELECT_FACE, "FACE", ICON_FACESEL, "Faces", ""}, + {0, NULL, 0, NULL, NULL}, + }; + + static EnumPropertyItem actions_items[] = { + {0, "DISABLE", 0, "Disable", "Disable selected markers"}, + {1, "ENABLE", 0, "Enable", "Enable selected markers"}, + {2, "TOGGLE", 0, "Toggle", "Toggle disabled flag for selected markers"}, + {0, NULL, 0, NULL, NULL} + }; + + /* identifiers */ + ot->name = "Select Mode"; + ot->idname = "MESH_OT_select_mode"; + ot->description = "Change selection mode"; + + /* api callbacks */ + ot->invoke = edbm_select_mode_invoke; + ot->exec = edbm_select_mode_exec; + ot->poll = ED_operator_editmesh; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + 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", ""); + 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); + + RNA_def_enum(ot->srna, "action", actions_items, 2, "Action", "Selection action to execute"); +} + /* ***************************************************** */ /* **************** LOOP SELECTS *************** */ @@ -1926,6 +1996,101 @@ 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) +{ + ToolSettings *ts = CTX_data_tool_settings(C); + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = NULL; + int ret = FALSE; + + if (obedit && obedit->type == OB_MESH) { + em = BMEdit_FromObject(obedit); + } + + if (em == NULL) { + return ret; + } + + switch (action) { + case -1: + /* already set */ + break; + case 0: /* disable */ + /* check we have something to do */ + if ((em->selectmode & selectmode_new) == 0) { + return FALSE; + } + em->selectmode &= ~selectmode_new; + break; + case 1: /* enable */ + /* check we have something to do */ + if ((em->selectmode & selectmode_new) != 0) { + 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; + } + em->selectmode ^= selectmode_new; + break; + default: + BLI_assert(0); + } + + switch (selectmode_new) { + case SCE_SELECT_VERTEX: + if (use_extend == 0 || em->selectmode == 0) + em->selectmode = SCE_SELECT_VERTEX; + ts->selectmode = em->selectmode; + EDBM_selectmode_set(em); + ret = TRUE; + break; + case SCE_SELECT_EDGE: + if (use_extend == 0 || em->selectmode == 0) { + if (use_expand) { + const short selmode_max = highest_order_bit_s(ts->selectmode); + if (selmode_max == SCE_SELECT_VERTEX) { + EDBM_selectmode_convert(em, selmode_max, SCE_SELECT_EDGE); + } + } + em->selectmode = SCE_SELECT_EDGE; + } + ts->selectmode = em->selectmode; + EDBM_selectmode_set(em); + ret = TRUE; + break; + case SCE_SELECT_FACE: + if (use_extend == 0 || em->selectmode == 0) { + if (use_expand) { + const short selmode_max = highest_order_bit_s(ts->selectmode); + if (ELEM(selmode_max, SCE_SELECT_VERTEX, SCE_SELECT_EDGE)) { + EDBM_selectmode_convert(em, selmode_max, SCE_SELECT_FACE); + } + } + + em->selectmode = SCE_SELECT_FACE; + } + ts->selectmode = em->selectmode; + EDBM_selectmode_set(em); + ret = TRUE; + break; + default: + BLI_assert(0); + break; + } + + if (ret == TRUE) { + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL); + } + + return ret; +} void EDBM_deselect_by_material(BMEditMesh *em, const short index, const short select) { diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 82b785e5785..8e63bd74ece 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -129,6 +129,7 @@ void MESH_OT_faces_select_linked_flat(struct wmOperatorType *ot); void MESH_OT_edges_select_sharp(struct wmOperatorType *ot); void MESH_OT_select_shortest_path(struct wmOperatorType *ot); void MESH_OT_select_similar(struct wmOperatorType *ot); +void MESH_OT_select_mode(struct wmOperatorType *ot); void MESH_OT_select_random(struct wmOperatorType *ot); void MESH_OT_loop_multi_select(struct wmOperatorType *ot); void MESH_OT_mark_seam(struct wmOperatorType *ot); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index d319fdcca26..91fb6e0c487 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -129,6 +129,7 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_edge_face_add); WM_operatortype_append(MESH_OT_select_shortest_path); WM_operatortype_append(MESH_OT_select_similar); + WM_operatortype_append(MESH_OT_select_mode); WM_operatortype_append(MESH_OT_loop_multi_select); WM_operatortype_append(MESH_OT_mark_seam); WM_operatortype_append(MESH_OT_mark_sharp); diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 7acb371041c..79bf003a563 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -310,21 +310,14 @@ static char *view3d_modeselect_pup(Scene *scene) return (string); } - static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event) { wmWindow *win = CTX_wm_window(C); - ToolSettings *ts = CTX_data_tool_settings(C); ScrArea *sa = CTX_wm_area(C); View3D *v3d = sa->spacedata.first; - Object *obedit = CTX_data_edit_object(C); - BMEditMesh *em = NULL; const int ctrl = win->eventstate->ctrl, shift = win->eventstate->shift; PointerRNA props_ptr; - - if (obedit && obedit->type == OB_MESH) { - em = BMEdit_FromObject(obedit); - } + /* watch it: if sa->win does not exist, check that when calling direct drawing routines */ switch (event) { @@ -336,47 +329,17 @@ static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event) break; case B_SEL_VERT: - if (em) { - if (shift == 0 || em->selectmode == 0) - em->selectmode = SCE_SELECT_VERTEX; - ts->selectmode = em->selectmode; - EDBM_selectmode_set(em); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + if (EDBM_selectmode_toggle(C, SCE_SELECT_VERTEX, -1, shift, ctrl)) { ED_undo_push(C, "Selectmode Set: Vertex"); } break; case B_SEL_EDGE: - if (em) { - if (shift == 0 || em->selectmode == 0) { - if (ctrl) { - const short selmode_max = highest_order_bit_s(ts->selectmode); - if (selmode_max == SCE_SELECT_VERTEX) { - EDBM_selectmode_convert(em, selmode_max, SCE_SELECT_EDGE); - } - } - em->selectmode = SCE_SELECT_EDGE; - } - ts->selectmode = em->selectmode; - EDBM_selectmode_set(em); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + if (EDBM_selectmode_toggle(C, SCE_SELECT_EDGE, -1, shift, ctrl)) { ED_undo_push(C, "Selectmode Set: Edge"); } break; case B_SEL_FACE: - if (em) { - if (shift == 0 || em->selectmode == 0) { - if (ctrl) { - const short selmode_max = highest_order_bit_s(ts->selectmode); - if (ELEM(selmode_max, SCE_SELECT_VERTEX, SCE_SELECT_EDGE)) { - EDBM_selectmode_convert(em, selmode_max, SCE_SELECT_FACE); - } - } - - em->selectmode = SCE_SELECT_FACE; - } - ts->selectmode = em->selectmode; - EDBM_selectmode_set(em); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + if (EDBM_selectmode_toggle(C, SCE_SELECT_FACE, -1, shift, ctrl)) { ED_undo_push(C, "Selectmode Set: Face"); } break; -- cgit v1.2.3