diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 13ff09d7f23..b669300b7e5 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -795,6 +795,9 @@ class USERPREF_PT_input(InputKeyMapPanel): sub.separator() + sub.label(text="Loop Cut:") + sub.prop(inputs, "loopcut_finish_on_release") + sub.label(text="Orbit Style:") sub.row().prop(inputs, "view_rotate_method", expand=True) diff --git a/source/blender/editors/mesh/loopcut.c b/source/blender/editors/mesh/loopcut.c index e0af2d1b61c..6c6d4e3bd4a 100644 --- a/source/blender/editors/mesh/loopcut.c +++ b/source/blender/editors/mesh/loopcut.c @@ -104,6 +104,9 @@ typedef struct tringselOpData { int extend; int do_cut; + + double leftmouse_time; + wmTimer *timer; } tringselOpData; /* modal loop selection drawing callback */ @@ -189,6 +192,8 @@ static void edgering_sel(tringselOpData *lcd, int previewlines, int select) float co[2][3]; int i, tot=0; + memset(v, 0, sizeof(v)); + if (!startedge) return; @@ -337,10 +342,13 @@ static void ringsel_finish(bContext *C, wmOperator *op) } /* called when modal loop selection is done... */ -static void ringsel_exit(bContext *UNUSED(C), wmOperator *op) +static void ringsel_exit(bContext *C, wmOperator *op) { tringselOpData *lcd= op->customdata; - + + if (lcd->timer) + WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), lcd->timer); + /* deactivate the extra drawing stuff in 3D-View */ ED_region_draw_cb_exit(lcd->ar->type, lcd->draw_handle); @@ -423,6 +431,10 @@ static int ringcut_invoke (bContext *C, wmOperator *op, wmEvent *evt) BMEdge *edge; int dist = 75; + /*if we're in the cut-n-slide macro, set release_confirm based on user pref*/ + if (op->opm) + RNA_boolean_set(op->next->ptr, "release_confirm", U.loopcut_finish_on_release); + if(modifiers_isDeformedByLattice(obedit) || modifiers_isDeformedByArmature(obedit)) BKE_report(op->reports, RPT_WARNING, "Loop cut doesn't work well on deformed edit mesh display"); @@ -448,68 +460,6 @@ static int ringcut_invoke (bContext *C, wmOperator *op, wmEvent *evt) return OPERATOR_RUNNING_MODAL; } -static int ringsel_modal (bContext *C, wmOperator *op, wmEvent *event) -{ - int cuts= RNA_int_get(op->ptr,"number_cuts"); - tringselOpData *lcd= op->customdata; - - view3d_operator_needs_opengl(C); - - - switch (event->type) { - case LEFTMOUSE: /* abort */ // XXX hardcoded - ED_region_tag_redraw(lcd->ar); - ringsel_exit(C, op); - - return OPERATOR_FINISHED; - case RETKEY: - case RIGHTMOUSE: /* confirm */ // XXX hardcoded - if (event->val == KM_PRESS) { - /* finish */ - ED_region_tag_redraw(lcd->ar); - - ringsel_finish(C, op); - ringsel_exit(C, op); - ED_area_headerprint(CTX_wm_area(C), NULL); - - return OPERATOR_FINISHED; - } - - ED_region_tag_redraw(lcd->ar); - break; - case ESCKEY: - if (event->val == KM_RELEASE) { - /* cancel */ - ED_region_tag_redraw(lcd->ar); - ED_area_headerprint(CTX_wm_area(C), NULL); - - return ringcut_cancel(C, op); - } - - ED_region_tag_redraw(lcd->ar); - break; - case MOUSEMOVE: { /* mouse moved somewhere to select another loop */ - int dist = 75; - BMEdge *edge; - - lcd->vc.mval[0] = event->mval[0]; - lcd->vc.mval[1] = event->mval[1]; - edge = EDBM_findnearestedge(&lcd->vc, &dist); - - if (edge != lcd->eed) { - lcd->eed = edge; - ringsel_find_edge(lcd, cuts); - } - - ED_region_tag_redraw(lcd->ar); - break; - } - } - - /* keep going until the user confirms */ - return OPERATOR_RUNNING_MODAL; -} - static int loopcut_modal (bContext *C, wmOperator *op, wmEvent *event) { int cuts= RNA_int_get(op->ptr,"number_cuts"); @@ -517,7 +467,6 @@ static int loopcut_modal (bContext *C, wmOperator *op, wmEvent *event) view3d_operator_needs_opengl(C); - switch (event->type) { case RETKEY: case LEFTMOUSE: /* confirm */ // XXX hardcoded @@ -528,20 +477,37 @@ static int loopcut_modal (bContext *C, wmOperator *op, wmEvent *event) ringsel_finish(C, op); ringsel_exit(C, op); - return OPERATOR_FINISHED; + ED_area_headerprint(CTX_wm_area(C), NULL); + + return OPERATOR_FINISHED|OPERATOR_ABORT_MACRO; + } else { + lcd->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER2, 0.12); } ED_region_tag_redraw(lcd->ar); break; + case TIMER2: + /* finish */ + ED_region_tag_redraw(lcd->ar); + + ringsel_finish(C, op); + ringsel_exit(C, op); + + ED_area_headerprint(CTX_wm_area(C), NULL); + + return OPERATOR_FINISHED; + case RIGHTMOUSE: /* abort */ // XXX hardcoded ED_region_tag_redraw(lcd->ar); ringsel_exit(C, op); + ED_area_headerprint(CTX_wm_area(C), NULL); return OPERATOR_FINISHED; case ESCKEY: if (event->val == KM_RELEASE) { /* cancel */ ED_region_tag_redraw(lcd->ar); + ED_area_headerprint(CTX_wm_area(C), NULL); return ringcut_cancel(C, op); } diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 9e70249d9e4..6201e8e532a 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -184,8 +184,10 @@ void ED_operatormacros_mesh(void) ot= WM_operatortype_append_macro("MESH_OT_loopcut_slide", "Loop Cut and Slide", OPTYPE_UNDO|OPTYPE_REGISTER); ot->description = "Cut mesh loop and slide it"; WM_operatortype_macro_define(ot, "MESH_OT_loopcut"); - WM_operatortype_macro_define(ot, "TRANSFORM_OT_edge_slide"); - + otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_edge_slide"); + + RNA_boolean_set(otmacro->ptr, "launch_event", LEFTMOUSE); + ot= WM_operatortype_append_macro("MESH_OT_duplicate_move", "Add Duplicate", OPTYPE_UNDO|OPTYPE_REGISTER); ot->description = "Duplicate mesh and move"; WM_operatortype_macro_define(ot, "MESH_OT_duplicate"); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 9fcf335c1bd..d0d328eb48e 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1522,6 +1522,8 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int t->mode = mode; t->launch_event = event ? event->type : -1; + if (RNA_property_is_set(op->ptr, "launch_event")) + t->launch_event = RNA_int_get(op->ptr, "launch_event"); if (t->launch_event == EVT_TWEAK_R) { diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 4edaabb9508..0cb81a3d4cc 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -499,6 +499,8 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) // Add confirm method all the time. At the end because it's not really that important and should be hidden only in log, not in keymap edit /*prop =*/ RNA_def_boolean(ot->srna, "release_confirm", 0, "Confirm on Release", "Always confirm operation when releasing button"); //RNA_def_property_flag(prop, PROP_HIDDEN); + + RNA_def_int(ot->srna, "launch_event", -1, 0, INT_MAX, "", "", -1, INT_MAX); } void TRANSFORM_OT_translate(struct wmOperatorType *ot) diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 3672e28644a..7a659809cb0 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -392,7 +392,7 @@ typedef struct UserDef { struct ColorBand coba_weight; /* from texture.h */ float sculpt_paint_overlay_col[3]; - int pad3; + int loopcut_finish_on_release; char author[80]; /* author name for file formats supporting it */ } UserDef; diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 769f0ad17db..6c3e52004c0 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -313,6 +313,7 @@ typedef struct wmOperator { #define OPERATOR_PASS_THROUGH 8 /* in case operator got executed outside WM code... like via fileselect */ #define OPERATOR_HANDLED 16 +#define OPERATOR_ABORT_MACRO 32 /* wmOperator flag */ #define OP_GRAB_POINTER 1 diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 687003b3421..6309044ad2c 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2679,6 +2679,10 @@ static void rna_def_userdef_input(BlenderRNA *brna) RNA_def_property_enum_bitflag_sdna(prop, NULL, "uiflag"); RNA_def_property_enum_items(prop, view_zoom_axes); RNA_def_property_ui_text(prop, "Zoom Axis", "Axis of mouse movement to zoom in or out on"); + + prop= RNA_def_property(srna, "loopcut_finish_on_release", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "loopcut_finish_on_release", 1); + RNA_def_property_ui_text(prop, "End Loopcut Slide On Release", "End Loopcut Slide On Mouse Release, a 'click-drag-and-hold' workflow"); prop= RNA_def_property(srna, "invert_mouse_wheel_zoom", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_ZOOM_INVERT); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index ae275096263..668de61e891 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -213,7 +213,7 @@ static int wm_macro_exec(bContext *C, wmOperator *op) if(opm->type->exec) { retval= opm->type->exec(C, opm); - if (retval & OPERATOR_FINISHED) { + if ((retval & OPERATOR_FINISHED) && !(retval & OPERATOR_ABORT_MACRO)) { MacroData *md = op->customdata; md->retval = OPERATOR_FINISHED; /* keep in mind that at least one operator finished */ } else { @@ -238,7 +238,7 @@ static int wm_macro_invoke_internal(bContext *C, wmOperator *op, wmEvent *event, BLI_movelisttolist(&op->reports->list, &opm->reports->list); - if (retval & OPERATOR_FINISHED) { + if ((retval & OPERATOR_FINISHED) && !(retval & OPERATOR_ABORT_MACRO)) { MacroData *md = op->customdata; md->retval = OPERATOR_FINISHED; /* keep in mind that at least one operator finished */ } else { @@ -266,7 +266,7 @@ static int wm_macro_modal(bContext *C, wmOperator *op, wmEvent *event) retval = opm->type->modal(C, opm, event); /* if this one is done but it's not the last operator in the macro */ - if ((retval & OPERATOR_FINISHED) && opm->next) { + if (opm->next && (retval & OPERATOR_FINISHED) && !(retval & OPERATOR_ABORT_MACRO)) { MacroData *md = op->customdata; md->retval = OPERATOR_FINISHED; /* keep in mind that at least one operator finished */