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.
This commit is contained in:
Campbell Barton 2012-11-13 05:44:49 +00:00
parent 590dbb87e7
commit add5dd3797
6 changed files with 179 additions and 53 deletions

@ -1736,18 +1736,9 @@ class VIEW3D_MT_edit_mesh_select_mode(Menu):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
props = layout.operator("wm.context_set_value", text="Vertex", icon='VERTEXSEL')
props.value = "(True, False, False)"
props.data_path = "tool_settings.mesh_select_mode"
props = layout.operator("wm.context_set_value", text="Edge", icon='EDGESEL')
props.value = "(False, True, False)"
props.data_path = "tool_settings.mesh_select_mode"
props = layout.operator("wm.context_set_value", text="Face", icon='FACESEL')
props.value = "(False, False, True)"
props.data_path = "tool_settings.mesh_select_mode"
layout.operator("mesh.select_mode", text="Vertex", icon='VERTEXSEL').type = 'VERT'
layout.operator("mesh.select_mode", text="Edge", icon='EDGESEL').type = 'EDGE'
layout.operator("mesh.select_mode", text="Face", icon='FACESEL').type = 'FACE'
class VIEW3D_MT_edit_mesh_extrude(Menu):

@ -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);

@ -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)
{

@ -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);

@ -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);

@ -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;