Fun stuff with macro
authorMartin Poirier <theeth@yahoo.com>
Tue, 17 Nov 2009 22:19:48 +0000 (22:19 +0000)
committerMartin Poirier <theeth@yahoo.com>
Tue, 17 Nov 2009 22:19:48 +0000 (22:19 +0000)
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
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_operators.c
source/blender/windowmanager/wm_event_system.h

index ea968bf6fc9e2b73d23f14ee54a286d230ef04c5..3ce5bbc7e5a58e13807a5a1b007d50777cdc006d 100644 (file)
@@ -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 */
index e5508d58145ac763f3199f9cbf7a6ae2f6898a9c..42c65a8a8d7cf75aaec948266e300d9dbba33e03 100644 (file)
@@ -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);
 }
index 892deea20812d17c305eae36c69b4cb492af797b..02b430683219e5e31bcf2c33d4fde5c8d348ff72 100644 (file)
@@ -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 */
index 4322f70ea613c5f5ad44e406ae546746f8ccf236..b7c881629a206dde78665e52f4b64b0997d03d07 100644 (file)
@@ -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);