From 7b05c9ca30cb61d808a7900886135e99719d9feb Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Tue, 17 Nov 2009 22:19:48 +0000 Subject: Fun stuff with macro Make macros work with more than one modal operator and mix of modal and invoke/exec As a proof, brought back loopcut + edge slide in a single macro operator called Loopcut and Slide, replacing Loopcut as assigned to Ctrl-R. --- source/blender/editors/mesh/mesh_ops.c | 11 ++--- .../blender/windowmanager/intern/wm_event_system.c | 2 +- source/blender/windowmanager/intern/wm_operators.c | 56 +++++++++++++++++----- source/blender/windowmanager/wm_event_system.h | 2 +- 4 files changed, 49 insertions(+), 22 deletions(-) diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index ea968bf6fc9..3ce5bbc7e5a 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -170,13 +170,10 @@ void ED_operatormacros_mesh(void) wmOperatorType *ot; wmOperatorTypeMacro *otmacro; int constraint_axis[3] = {0, 0, 1}; - - /*combining operators with invoke and exec portions doesn't work yet. - ot= WM_operatortype_append_macro("MESH_OT_loopcut", "Loopcut", OPTYPE_UNDO|OPTYPE_REGISTER); - WM_operatortype_macro_define(ot, "MESH_OT_edgering_select"); - WM_operatortype_macro_define(ot, "MESH_OT_subdivide"); - */ + ot= WM_operatortype_append_macro("MESH_OT_loopcut_slide", "Loopcut and Slide", OPTYPE_UNDO|OPTYPE_REGISTER); + WM_operatortype_macro_define(ot, "MESH_OT_loopcut"); + WM_operatortype_macro_define(ot, "TFM_OT_edge_slide"); ot= WM_operatortype_append_macro("MESH_OT_duplicate_move", "Add Duplicate", OPTYPE_UNDO|OPTYPE_REGISTER); WM_operatortype_macro_define(ot, "MESH_OT_duplicate"); @@ -211,7 +208,7 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) keymap= WM_keymap_find(keyconf, "EditMesh", 0, 0); keymap->poll= ED_operator_editmesh; - WM_keymap_add_item(keymap, "MESH_OT_loopcut", RKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "MESH_OT_loopcut_slide", RKEY, KM_PRESS, KM_CTRL, 0); /* selecting */ /* standard mouse selection goes via space_view3d */ diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index e5508d58145..42c65a8a8d7 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -621,7 +621,7 @@ int WM_operator_call_py(bContext *C, wmOperatorType *ot, int context, PointerRNA /* ********************* handlers *************** */ /* future extra customadata free? */ -static void wm_event_free_handler(wmEventHandler *handler) +void wm_event_free_handler(wmEventHandler *handler) { MEM_freeN(handler); } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 892deea2081..02b43068321 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -193,20 +193,20 @@ static int wm_macro_exec(bContext *C, wmOperator *op) return retval; } -static int wm_macro_invoke(bContext *C, wmOperator *op, wmEvent *event) +int wm_macro_invoke_internal(bContext *C, wmOperator *op, wmEvent *event, wmOperator *opm) { - wmOperator *opm; int retval= OPERATOR_FINISHED; - + // printf("macro invoke %s\n", op->type->idname); - - for(opm= op->macro.first; opm; opm= opm->next) { - + + /* start from operator received as argument */ + for( ; opm; opm= opm->next) { + if(opm->type->invoke) retval= opm->type->invoke(C, opm, event); else if(opm->type->exec) retval= opm->type->exec(C, opm); - + /* if modal, pass operator flags to macro, they may be needed later */ if(retval & OPERATOR_RUNNING_MODAL) op->flag = opm->flag; @@ -214,28 +214,58 @@ static int wm_macro_invoke(bContext *C, wmOperator *op, wmEvent *event) if(!(retval & OPERATOR_FINISHED)) break; } - + // if(opm) // printf("macro ended not finished\n"); // else // printf("macro end\n"); - - + + return retval; } +static int wm_macro_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + return wm_macro_invoke_internal(C, op, event, op->macro.first); +} + static int wm_macro_modal(bContext *C, wmOperator *op, wmEvent *event) { + wmOperator *opm = op->opm; + int retval= OPERATOR_FINISHED; // printf("macro modal %s\n", op->type->idname); - if(op->opm==NULL) + if(opm==NULL) printf("macro error, calling NULL modal()\n"); else { // printf("macro modal %s\n", op->opm->type->idname); - return op->opm->type->modal(C, op->opm, 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) { + retval = wm_macro_invoke_internal(C, op, event, opm->next); + + /* if new operator is modal and also added its own handler */ + if (retval & OPERATOR_RUNNING_MODAL && op->opm != opm) { + wmWindow *win = CTX_wm_window(C); + wmEventHandler *handler = NULL; + + for (handler = win->modalhandlers.first; handler; handler = handler->next) { + /* first handler in list is the new one */ + if (handler->op == op) + break; + } + + if (handler) { + BLI_remlink(&win->modalhandlers, handler); + wm_event_free_handler(handler); + } + } + + } } - return OPERATOR_FINISHED; + return retval; } /* Names have to be static for now */ diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h index 4322f70ea61..b7c881629a2 100644 --- a/source/blender/windowmanager/wm_event_system.h +++ b/source/blender/windowmanager/wm_event_system.h @@ -82,7 +82,7 @@ enum { void wm_event_add (wmWindow *win, wmEvent *event_to_add); void wm_event_free_all (wmWindow *win); void wm_event_free (wmEvent *event); - +void wm_event_free_handler (wmEventHandler *handler); /* goes over entire hierarchy: events -> window -> screen -> area -> region */ void wm_event_do_handlers (bContext *C); -- cgit v1.2.3