2.5
authorTon Roosendaal <ton@blender.org>
Wed, 29 Jul 2009 17:56:38 +0000 (17:56 +0000)
committerTon Roosendaal <ton@blender.org>
Wed, 29 Jul 2009 17:56:38 +0000 (17:56 +0000)
Operator goodies!

--- Macro operators

Operators now can consist of multiple operators. Such a macro operator
is identical and behaves identical to other opererators. Macros can
also be constructed of macros even! Currently only hardcoded macros are
implemented, this to solve combined operators such as 'add duplicate' or
'extrude' (both want a transform appended).

Usage is simple:
- WM_operatortype_append_macro() : add new operatortype, name, flags
- WM_operatortype_macro_define() : add existing operator to macro

(Note: macro_define will also allow properties to be set, doesnt work
 right now)

On converting the macro wmOperatorType to a real operator, it makes a
list of all operators, and the standard macro callbacks (exec, invoke,
modal, poll) just will use all.

Important note; switching to a modal operator only works as last in the
chain now!

Macros implemented for duplicate, extrude and rip. Tool menu works fine
for it, also the redo hotkey F4 works properly.

--- Operator redo fix

The operators use the undo system to switch back, but this could give
errors if other actions added undo pushes (buttons, outliner). Now the
redo for operator searches back for the correct undo level.

This fixes issues with many redos.

Note for brecht: removed the ED_undo_push for buttons... it was called
on *every* button now, which is probably too much? For example, using
the 'toolbar' redo also caused this...

21 files changed:
source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/intern/blender.c
source/blender/editors/include/ED_util.h
source/blender/editors/interface/interface_handlers.c
source/blender/editors/mesh/editmesh_add.c
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/mesh/mesh_ops.c
source/blender/editors/object/object_edit.c
source/blender/editors/object/object_ops.c
source/blender/editors/space_view3d/view3d_edit.c
source/blender/editors/space_view3d/view3d_ops.c
source/blender/editors/space_view3d/view3d_toolbar.c
source/blender/editors/util/editmode_undo.c
source/blender/editors/util/undo.c
source/blender/editors/util/util_intern.h
source/blender/makesdna/DNA_windowmanager_types.h
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/WM_types.h
source/blender/windowmanager/intern/wm.c
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_operators.c

index 795c7585b9ca9cab8cf32c9401579e11db2dca64..19b9c315939f90c1eeaa72b2b19370364ac9ef61 100644 (file)
@@ -71,6 +71,7 @@ void pushpop_test(void);
 /* global undo */
 extern void BKE_write_undo(struct bContext *C, char *name);
 extern void BKE_undo_step(struct bContext *C, int step);
+extern void BKE_undo_name(struct bContext *C, const char *name);
 extern void BKE_reset_undo(void);
 extern char *BKE_undo_menu_string(void);
 extern void BKE_undo_number(struct bContext *C, int nr);
index 20505356d9569c45db6ce4c2bd8dde972e85a87e..2728aa30e6ee60dcbf8fe21c780d30401c921cde 100644 (file)
@@ -688,6 +688,22 @@ void BKE_undo_number(bContext *C, int nr)
        BKE_undo_step(C, 0);
 }
 
+/* go back to the last occurance of name in stack */
+void BKE_undo_name(bContext *C, const char *name)
+{
+       UndoElem *uel;
+       
+       for(uel= undobase.last; uel; uel= uel->prev) {
+               if(strcmp(name, uel->name)==0)
+                       break;
+       }
+       if(uel && uel->prev) {
+               curundo= uel->prev;
+               BKE_undo_step(C, 0);
+       }
+}
+
+
 char *BKE_undo_menu_string(void)
 {
        UndoElem *uel;
index 7ccbf1ff18dae160c2e031347782fea9eae17041..7b1c87f9cb2bab2ef9d0ffb12d1bf07a74423dec 100644 (file)
@@ -44,6 +44,7 @@ void  ED_editors_exit                 (struct bContext *C);
 /* undo.c */
 void   ED_undo_push                    (struct bContext *C, char *str);
 void   ED_undo_push_op                 (struct bContext *C, struct wmOperator *op);
+void   ED_undo_pop_op                  (struct bContext *C, struct wmOperator *op);
 void   ED_undo_pop                             (struct bContext *C);
 void   ED_undo_redo                    (struct bContext *C);
 void   ED_OT_undo                              (struct wmOperatorType *ot);
index da2899dd3b21892ff0ca265c9e2a138989ddf111..6f2b49c0513e2bab97408918b9815611eac384c5 100644 (file)
@@ -358,8 +358,8 @@ static void ui_apply_but_funcs_after(bContext *C)
                if(after.rename_orig)
                        MEM_freeN(after.rename_orig);
                
-               if(after.undostr[0])
-                       ED_undo_push(C, after.undostr);
+//             if(after.undostr[0])
+//                     ED_undo_push(C, after.undostr);
        }
 }
 
index 92aa46ea3903ac897ef8919af2d50a817c5ccdc6..34eca8748bc577723856183f299a219756dc7eb1 100644 (file)
@@ -1683,9 +1683,6 @@ static int mesh_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event)
        mesh_duplicate_exec(C, op);
        WM_cursor_wait(0);
        
-       RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
-       WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
-       
        return OPERATOR_FINISHED;
 }
 
index 76f355ab7f9bebf399ee729c44d5beb7345ecd4b..93e91732b2b7e089e538dc9f19f844e28b7bfe97 100644 (file)
@@ -704,7 +704,7 @@ static int mesh_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event)
        Scene *scene= CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
        EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-       int constraint_axis[3] = {0, 0, 1};
+//     int constraint_axis[3] = {0, 0, 1};
 
        extrude_mesh(scene, obedit, em, op);
 
@@ -717,11 +717,11 @@ static int mesh_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event)
        RNA_boolean_set(op->ptr, "mirror", 0);
        
        /* the following two should only be set when extruding faces */
-       RNA_enum_set(op->ptr, "constraint_orientation", V3D_MANIP_NORMAL);
-       RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis);
+//     RNA_enum_set(op->ptr, "constraint_orientation", V3D_MANIP_NORMAL);
+//     RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis);
        
        
-       WM_operator_name_call(C, "TFM_OT_translate", WM_OP_INVOKE_REGION_WIN, op->ptr);
+//     WM_operator_name_call(C, "TFM_OT_translate", WM_OP_INVOKE_REGION_WIN, op->ptr);
 
        return OPERATOR_FINISHED;
 }
@@ -4991,9 +4991,9 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
 
        BKE_mesh_end_editmesh(obedit->data, em);
 
-       RNA_enum_set(op->ptr, "proportional", 0);
-       RNA_boolean_set(op->ptr, "mirror", 0);
-       WM_operator_name_call(C, "TFM_OT_translate", WM_OP_INVOKE_REGION_WIN, op->ptr);
+//     RNA_enum_set(op->ptr, "proportional", 0);
+//     RNA_boolean_set(op->ptr, "mirror", 0);
+//     WM_operator_name_call(C, "TFM_OT_translate", WM_OP_INVOKE_REGION_WIN, op->ptr);
 
        return OPERATOR_FINISHED;
 }
index 8ed68d5cd2060f5a821faf19c2b5e258c912f285..edb131d7da2e9f556a5462b098c8fda0dc3a420a 100644 (file)
@@ -230,6 +230,8 @@ static void MESH_OT_specials(wmOperatorType *ot)
 
 void ED_operatortypes_mesh(void)
 {
+       wmOperatorType *ot;
+       
        WM_operatortype_append(MESH_OT_select_all_toggle);
        WM_operatortype_append(MESH_OT_select_more);
        WM_operatortype_append(MESH_OT_select_less);
@@ -313,6 +315,20 @@ void ED_operatortypes_mesh(void)
        WM_operatortype_append(MESH_OT_edge_specials);
        WM_operatortype_append(MESH_OT_face_specials);
        WM_operatortype_append(MESH_OT_specials);
+       
+       /* macros */
+       ot= WM_operatortype_append_macro("MESH_OT_duplicate_move", "Add Duplicate", OPTYPE_UNDO|OPTYPE_REGISTER);
+       WM_operatortype_macro_define(ot, "MESH_OT_duplicate");
+       WM_operatortype_macro_define(ot, "TFM_OT_translate");
+
+       ot= WM_operatortype_append_macro("MESH_OT_rip_move", "Rip", OPTYPE_UNDO|OPTYPE_REGISTER);
+       WM_operatortype_macro_define(ot, "MESH_OT_rip");
+       WM_operatortype_macro_define(ot, "TFM_OT_translate");
+
+       ot= WM_operatortype_append_macro("MESH_OT_extrude_move", "Extrude", OPTYPE_UNDO|OPTYPE_REGISTER);
+       WM_operatortype_macro_define(ot, "MESH_OT_extrude");
+       WM_operatortype_macro_define(ot, "TFM_OT_translate");
+       
 }
 
 /* note mesh keymap also for other space? */
@@ -363,7 +379,7 @@ void ED_keymap_mesh(wmWindowManager *wm)
        WM_keymap_add_item(keymap, "MESH_OT_normals_make_consistent", NKEY, KM_PRESS, KM_CTRL, 0);
        RNA_boolean_set(WM_keymap_add_item(keymap, "MESH_OT_normals_make_consistent", NKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0)->ptr, "inside", 1);
        
-       WM_keymap_add_item(keymap, "MESH_OT_extrude", EKEY, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "MESH_OT_extrude_move", EKEY, KM_PRESS, 0, 0);
        
        WM_keymap_add_item(keymap, "MESH_OT_spin", RKEY, KM_PRESS, KM_ALT, 0);
        WM_keymap_add_item(keymap, "MESH_OT_screw", NINEKEY, KM_PRESS, KM_CTRL, 0);
@@ -386,12 +402,12 @@ void ED_keymap_mesh(wmWindowManager *wm)
        WM_keymap_add_item(keymap, "MESH_OT_colors_rotate",EIGHTKEY, KM_PRESS, KM_CTRL, 0);
        WM_keymap_add_item(keymap, "MESH_OT_colors_mirror",EIGHTKEY, KM_PRESS, KM_ALT, 0);
 
-       WM_keymap_add_item(keymap, "MESH_OT_rip",VKEY, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "MESH_OT_rip_move",VKEY, KM_PRESS, 0, 0);
        WM_keymap_add_item(keymap, "MESH_OT_merge", MKEY, KM_PRESS, KM_ALT, 0);
 
        /* add/remove */
        WM_keymap_add_item(keymap, "MESH_OT_edge_face_add", FKEY, KM_PRESS, 0, 0);
-       WM_keymap_add_item(keymap, "MESH_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0);
+       WM_keymap_add_item(keymap, "MESH_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
        WM_keymap_add_item(keymap, "OBJECT_OT_mesh_add", AKEY, KM_PRESS, KM_SHIFT, 0);
        WM_keymap_add_item(keymap, "MESH_OT_separate", PKEY, KM_PRESS, KM_SHIFT, 0);
                                                /* use KM_RELEASE because same key is used for tweaks */
index f34dc2e7c2372a6adc987374562d8e54865b57a8..5fd5f4ff0ad8204d3d7c63b95d36e1c82a30d85e 100644 (file)
@@ -6497,8 +6497,8 @@ static int duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
        duplicate_exec(C, op);
        
-       RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
-       WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
+//     RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
+//     WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
 
        return OPERATOR_FINISHED;
 }
index fe09284718309f6f9839c1d277fee48c57b098ff..c1509e7850277e54600d75cc3a81ddf0b9d5ec7c 100644 (file)
@@ -63,6 +63,8 @@
 
 void ED_operatortypes_object(void)
 {
+       wmOperatorType *ot;
+       
        WM_operatortype_append(OBJECT_OT_editmode_toggle);
        WM_operatortype_append(OBJECT_OT_posemode_toggle);
        WM_operatortype_append(OBJECT_OT_parent_set);
@@ -147,6 +149,13 @@ void ED_operatortypes_object(void)
 
        WM_operatortype_append(LATTICE_OT_select_all_toggle);
        WM_operatortype_append(LATTICE_OT_make_regular);
+       
+       /* macros */
+       ot= WM_operatortype_append_macro("OBJECT_OT_duplicate_move", "Add Duplicate", OPTYPE_UNDO|OPTYPE_REGISTER);
+       if(ot) {
+               WM_operatortype_macro_define(ot, "OBJECT_OT_duplicate");
+               WM_operatortype_macro_define(ot, "TFM_OT_translate");
+       }
 }
 
 void ED_keymap_object(wmWindowManager *wm)
@@ -185,7 +194,7 @@ void ED_keymap_object(wmWindowManager *wm)
        
        WM_keymap_verify_item(keymap, "OBJECT_OT_delete", XKEY, KM_PRESS, 0, 0);
        WM_keymap_verify_item(keymap, "OBJECT_OT_primitive_add", AKEY, KM_PRESS, KM_SHIFT, 0);
-       WM_keymap_add_item(keymap, "OBJECT_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0);
+       WM_keymap_add_item(keymap, "OBJECT_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
        RNA_boolean_set(WM_keymap_add_item(keymap, "OBJECT_OT_duplicate", DKEY, KM_PRESS, KM_ALT, 0)->ptr, "linked", 1);
        WM_keymap_add_item(keymap, "OBJECT_OT_join", JKEY, KM_PRESS, KM_CTRL, 0);
        WM_keymap_add_item(keymap, "OBJECT_OT_proxy_make", PKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
index f278b717f10531a4d1c2d6d00faa769ef78962b2..acb3a2257dc1a1d04f539baf09cc5e6018cd20bd 100644 (file)
@@ -560,7 +560,7 @@ void VIEW3D_OT_viewrotate(wmOperatorType *ot)
        ot->poll= ED_operator_view3d_active;
 
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_BLOCKING;
+       ot->flag= OPTYPE_BLOCKING;
 }
 
 /* ************************ viewmove ******************************** */
@@ -644,7 +644,7 @@ void VIEW3D_OT_viewmove(wmOperatorType *ot)
        ot->poll= ED_operator_view3d_active;
 
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_BLOCKING;
+       ot->flag= OPTYPE_BLOCKING;
 }
 
 /* ************************ viewzoom ******************************** */
@@ -844,7 +844,7 @@ void VIEW3D_OT_zoom(wmOperatorType *ot)
        ot->poll= ED_operator_view3d_active;
 
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_BLOCKING;
+       ot->flag= OPTYPE_BLOCKING;
 
        RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
 }
@@ -925,7 +925,7 @@ void VIEW3D_OT_view_all(wmOperatorType *ot)
        ot->poll= ED_operator_view3d_active;
 
        /* flags */
-       ot->flag= OPTYPE_REGISTER;
+       ot->flag= 0;
 
        RNA_def_boolean(ot->srna, "center", 0, "Center", "");
 }
@@ -1064,7 +1064,7 @@ void VIEW3D_OT_view_center(wmOperatorType *ot)
        ot->poll= ED_operator_view3d_active;
 
        /* flags */
-       ot->flag= OPTYPE_REGISTER;
+       ot->flag= 0;
 }
 
 /* ********************* Set render border operator ****************** */
@@ -1312,7 +1312,7 @@ void VIEW3D_OT_zoom_border(wmOperatorType *ot)
        ot->poll= ED_operator_view3d_active;
 
        /* flags */
-       ot->flag= OPTYPE_REGISTER;
+       ot->flag= 0;
 
        /* rna */
        RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
@@ -1477,7 +1477,7 @@ void VIEW3D_OT_viewnumpad(wmOperatorType *ot)
        ot->poll= ED_operator_view3d_active;
 
        /* flags */
-       ot->flag= OPTYPE_REGISTER;
+       ot->flag= 0;
 
        RNA_def_enum(ot->srna, "type", prop_view_items, 0, "View", "The Type of view");
 }
@@ -1546,7 +1546,7 @@ void VIEW3D_OT_view_orbit(wmOperatorType *ot)
        ot->poll= ED_operator_view3d_active;
 
        /* flags */
-       ot->flag= OPTYPE_REGISTER;
+       ot->flag= 0;
        RNA_def_enum(ot->srna, "type", prop_view_orbit_items, 0, "Orbit", "Direction of View Orbit");
 }
 
@@ -1596,7 +1596,7 @@ void VIEW3D_OT_view_pan(wmOperatorType *ot)
        ot->poll= ED_operator_view3d_active;
 
        /* flags */
-       ot->flag= OPTYPE_REGISTER;
+       ot->flag= 0;
        RNA_def_enum(ot->srna, "type", prop_view_pan_items, 0, "Pan", "Direction of View Pan");
 }
 
@@ -1628,7 +1628,7 @@ void VIEW3D_OT_view_persportho(wmOperatorType *ot)
        ot->poll= ED_operator_view3d_active;
 
        /* flags */
-       ot->flag= OPTYPE_REGISTER;
+       ot->flag= 0;
 }
 
 
@@ -1730,7 +1730,7 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot)
        ot->poll= ED_operator_view3d_active;
 
        /* flags */
-       ot->flag= OPTYPE_REGISTER;
+       ot->flag= 0;
 
        /* rna */
        RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
@@ -1783,7 +1783,7 @@ void VIEW3D_OT_drawtype(wmOperatorType *ot)
        ot->poll= ED_operator_view3d_active;
 
        /* flags */
-       ot->flag= OPTYPE_REGISTER;
+       ot->flag= 0;
 
        /* rna XXX should become enum */
        RNA_def_int(ot->srna, "draw_type", 0, INT_MIN, INT_MAX, "Draw Type", "", INT_MIN, INT_MAX);
index 69b297b2e03153d63e235fc09659439171403482..c82db3bbe323b331768c558d1af0123ffee3488a 100644 (file)
@@ -218,8 +218,8 @@ void view3d_keymap(wmWindowManager *wm)
        
        WM_keymap_add_item(keymap, "VIEW3D_OT_snap_menu", SKEY, KM_PRESS, KM_SHIFT, 0);
 
-       /* drag & drop */
-       WM_keymap_add_item(keymap, "VIEW3D_OT_drag", MOUSEDRAG, KM_ANY, 0, 0);
+       /* drag & drop (disabled) */
+//     WM_keymap_add_item(keymap, "VIEW3D_OT_drag", MOUSEDRAG, KM_ANY, 0, 0);
        
        /* radial control */
        RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE);
index 1564fcb169bd0bee83abc370472e8255f25238c4..67d8bc3e5ee5dec48a89539310fe2f4fd6d8845a 100644 (file)
@@ -109,7 +109,7 @@ static void redo_cb(bContext *C, void *arg_op, void *arg2)
                int retval;
                
                printf("operator redo %s\n", lastop->type->name);
-               ED_undo_pop(C);
+               ED_undo_pop_op(C, lastop);
                retval= WM_operator_repeat(C, lastop);
                if((retval & OPERATOR_FINISHED)==0) {
                        printf("operator redo failed %s\n", lastop->type->name);
@@ -118,11 +118,25 @@ static void redo_cb(bContext *C, void *arg_op, void *arg2)
        }
 }
 
+static void view3d_panel_operator_redo_buts(const bContext *C, Panel *pa, wmOperator *op)
+{
+       wmWindowManager *wm= CTX_wm_manager(C);
+       PointerRNA ptr;
+       
+       if(!op->properties) {
+               IDPropertyTemplate val = {0};
+               op->properties= IDP_New(IDP_GROUP, val, "wmOperatorProperties");
+       }
+       
+       RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+       uiDefAutoButsRNA(C, pa->layout, &ptr, 1);
+       
+}
+
 static void view3d_panel_operator_redo(const bContext *C, Panel *pa)
 {
        wmWindowManager *wm= CTX_wm_manager(C);
        wmOperator *op;
-       PointerRNA ptr;
        uiBlock *block;
        
        block= uiLayoutGetBlock(pa->layout);
@@ -139,13 +153,13 @@ static void view3d_panel_operator_redo(const bContext *C, Panel *pa)
        
        uiBlockSetFunc(block, redo_cb, op, NULL);
        
-       if(!op->properties) {
-               IDPropertyTemplate val = {0};
-               op->properties= IDP_New(IDP_GROUP, val, "wmOperatorProperties");
+       if(op->macro.first) {
+               for(op= op->macro.first; op; op= op->next)
+                       view3d_panel_operator_redo_buts(C, pa, op);
+       }
+       else {
+               view3d_panel_operator_redo_buts(C, pa, op);
        }
-       
-       RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
-       uiDefAutoButsRNA(C, pa->layout, &ptr, 1);
 }
 
 /* ******************* */
index 8484ad78bc4bcc733ab08865329002dc5f719f95..17a1e0b6cdbeb97dfaae93aeed3e7a0af5bacd6e 100644 (file)
@@ -297,6 +297,21 @@ static void undo_number(bContext *C, int nr)
        undo_editmode_step(C, 0);
 }
 
+void undo_editmode_name(bContext *C, const char *undoname)
+{
+       UndoElem *uel;
+       
+       for(uel= undobase.last; uel; uel= uel->prev) {
+               if(strcmp(undoname, uel->name)==0)
+                       break;
+       }
+       if(uel && uel->prev) {
+               curundo= uel->prev;
+               undo_editmode_step(C, 0);
+       }
+}
+
+
 /* ************** for interaction with menu/pullown */
 
 void undo_editmode_menu(bContext *C)
index be04cdecac60293a7ce873d2f80ee0c3d6ead0b2..435f2c7ecf45614db561a242ccc67cf58ab19d58 100644 (file)
@@ -71,6 +71,8 @@
 #include "UI_interface.h"
 #include "UI_resources.h"
 
+#include "util_intern.h"
+
 /* ***************** generic undo system ********************* */
 
 /* ********* XXX **************** */
@@ -81,7 +83,7 @@ void ED_undo_push(bContext *C, char *str)
 {
        wmWindowManager *wm= CTX_wm_manager(C);
        Object *obedit= CTX_data_edit_object(C);
-       
+
        if(obedit) {
                if (U.undosteps == 0) return;
                
@@ -114,13 +116,7 @@ void ED_undo_push(bContext *C, char *str)
        }
 }
 
-void ED_undo_push_op(bContext *C, wmOperator *op)
-{
-       /* in future, get undo string info? */
-       ED_undo_push(C, op->type->name);
-}
-
-static int ed_undo_step(bContext *C, int step)
+static int ed_undo_step(bContext *C, int step, const char *undoname)
 {      
        Object *obedit= CTX_data_edit_object(C);
        ScrArea *sa= CTX_wm_area(C);
@@ -140,8 +136,12 @@ static int ed_undo_step(bContext *C, int step)
                ED_text_undo_step(C, step);
        }
        else if(obedit) {
-               if ELEM7(obedit->type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL, OB_LATTICE, OB_ARMATURE)
-                       undo_editmode_step(C, step);
+               if ELEM7(obedit->type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL, OB_LATTICE, OB_ARMATURE) {
+                       if(undoname)
+                               undo_editmode_name(C, undoname);
+                       else
+                               undo_editmode_step(C, step);
+               }
        }
        else {
                int do_glob_undo= 0;
@@ -163,7 +163,10 @@ static int ed_undo_step(bContext *C, int step)
 #ifndef DISABLE_PYTHON
                                // XXX          BPY_scripts_clear_pyobjects();
 #endif
-                               BKE_undo_step(C, step);
+                               if(undoname)
+                                       BKE_undo_name(C, undoname);
+                               else
+                                       BKE_undo_step(C, step);
                                sound_initialize_sounds();
                        }
                        
@@ -177,22 +180,35 @@ static int ed_undo_step(bContext *C, int step)
 
 void ED_undo_pop(bContext *C)
 {
-       ed_undo_step(C, 1);
+       ed_undo_step(C, 1, NULL);
 }
 void ED_undo_redo(bContext *C)
 {
-       ed_undo_step(C, -1);
+       ed_undo_step(C, -1, NULL);
+}
+
+void ED_undo_push_op(bContext *C, wmOperator *op)
+{
+       /* in future, get undo string info? */
+       ED_undo_push(C, op->type->name);
+}
+
+void ED_undo_pop_op(bContext *C, wmOperator *op)
+{
+       /* search back a couple of undo's, in case something else added pushes */
+       ed_undo_step(C, 0, op->type->name);
 }
 
 static int ed_undo_exec(bContext *C, wmOperator *op)
 {
        /* "last operator" should disappear, later we can tie ths with undo stack nicer */
        WM_operator_stack_clear(C);
-       return ed_undo_step(C, 1);
+       return ed_undo_step(C, 1, NULL);
 }
+
 static int ed_redo_exec(bContext *C, wmOperator *op)
 {
-       return ed_undo_step(C, -1);
+       return ed_undo_step(C, -1, NULL);
 }
 
 void ED_undo_menu(bContext *C)
index 37e6c5c25e1ed7e2cd8375726d5e3c5827a9bc62..8a0787dde3f0d7c159f2553409290be5858d391f 100644 (file)
@@ -33,6 +33,7 @@
 
 /* editmode_undo.c */
 void undo_editmode_clear(void);
+void undo_editmode_name(bContext *C, const char *undoname);
 
 #endif /* ED_UTIL_INTERN_H */
 
index a7ad502d43885f216d1a7ffb111d4a8e83bce632..704acbfd52b66854357de50a76339420d58655c0 100644 (file)
@@ -171,6 +171,18 @@ typedef struct wmWindow {
 /* should be somthing like DNA_EXCLUDE 
  * but the preprocessor first removes all comments, spaces etc */
 
+#
+#
+typedef struct wmOperatorTypeMacro {
+       struct wmOperatorTypeMacro *next, *prev;
+       
+       /* operator id */
+       char idname[MAX_ID_NAME];
+       /* rna pointer to access properties, like keymap */
+       struct PointerRNA *ptr; 
+
+} wmOperatorTypeMacro;
+
 #
 #
 typedef struct wmOperatorType {
@@ -204,6 +216,9 @@ typedef struct wmOperatorType {
        /* rna for properties */
        struct StructRNA *srna;
        
+       /* struct wmOperatorTypeMacro */
+       ListBase macro;
+       
        short flag;
        
        /* pointer to modal keymap, do not free! */
@@ -265,9 +280,13 @@ typedef struct wmOperator {
        /* runtime */
        wmOperatorType *type;           /* operator type definition from idname */
        void *customdata;                       /* custom storage, only while operator runs */
+       
        struct PointerRNA *ptr;         /* rna pointer to access properties */
        struct ReportList *reports;     /* errors and warnings storage */
        
+       ListBase macro;                         /* list of operators, can be a tree */
+       struct wmOperator *opm;         /* current running macro, not saved */
+       
 } wmOperator;
 
 /* operator type exec(), invoke() modal(), return values */
index 0d3ad96d8c391e97a2c21d626c99d306a77025cd..f65e5b1b0773e346f2e56ee9d122c2e57bdc23fc 100644 (file)
@@ -158,6 +158,10 @@ void               WM_operatortype_append  (void (*opfunc)(wmOperatorType*));
 void           WM_operatortype_append_ptr      (void (*opfunc)(wmOperatorType*, void *), void *userdata);
 int                    WM_operatortype_remove(const char *idname);
 
+wmOperatorType *WM_operatortype_append_macro(char *idname, char *name, int flag);
+wmOperatorTypeMacro *WM_operatortype_macro_define(wmOperatorType *ot, const char *idname);
+
+
 int                    WM_operator_call                (struct bContext *C, struct wmOperator *op);
 int                    WM_operator_repeat              (struct bContext *C, struct wmOperator *op);
 int         WM_operator_name_call      (struct bContext *C, const char *opstring, int context, struct PointerRNA *properties);
index 3a646c5e799cb7936bab9ec2b894569aa64b6fbe..a083d589d31a230ab5ac9edded490368f4cdb74a 100644 (file)
@@ -43,6 +43,7 @@ struct wmWindowManager;
 #define OPTYPE_REGISTER                1       /* register operators in stack after finishing */
 #define OPTYPE_UNDO                    2       /* do undo push after after */
 #define OPTYPE_BLOCKING                4       /* let blender grab all input from the WM (X11) */
+#define OPTYPE_MACRO           8
 
 /* context to call operator in for WM_operator_name_call */
 /* rna_ui.c contains EnumPropertyItem's of these, keep in sync */
index 863fb3ab4bd750ef0b818a8ffcdb01e03835cc5e..c0ac7b06f5a8a0106b47802430588899cd1fec77 100644 (file)
@@ -74,6 +74,12 @@ void WM_operator_free(wmOperator *op)
                MEM_freeN(op->reports);
        }
 
+       if(op->macro.first) {
+               wmOperator *opm;
+               for(opm= op->macro.first; opm; opm= opm->next) 
+                       WM_operator_free(opm);
+       }
+       
        MEM_freeN(op);
 }
 
index c75feafe6231cea21fd09f0603e5f24abb99f662..33e8a392ba3164d9aedfd27f4819101ee82d1b78 100644 (file)
@@ -244,6 +244,23 @@ void wm_event_do_notifiers(bContext *C)
 
 /* ********************* operators ******************* */
 
+static int wm_operator_poll(bContext *C, wmOperatorType *ot)
+{
+       wmOperatorTypeMacro *otmacro;
+       
+       for(otmacro= ot->macro.first; otmacro; otmacro= otmacro->next) {
+               wmOperatorType *ot= WM_operatortype_find(otmacro->idname, 0);
+               
+               if(0==wm_operator_poll(C, ot))
+                       return 0;
+       }
+       
+       if(ot->poll)
+               return ot->poll(C);
+       
+       return 1;
+}
+
 /* if repeat is true, it doesn't register again, nor does it free */
 static int wm_operator_exec(bContext *C, wmOperator *op, int repeat)
 {
@@ -252,7 +269,7 @@ static int wm_operator_exec(bContext *C, wmOperator *op, int repeat)
        if(op==NULL || op->type==NULL)
                return retval;
        
-       if(op->type->poll && op->type->poll(C)==0)
+       if(0==wm_operator_poll(C, op->type))
                return retval;
        
        if(op->type->exec)
@@ -320,6 +337,26 @@ static wmOperator *wm_operator_create(wmWindowManager *wm, wmOperatorType *ot, P
                BKE_reports_init(op->reports, RPT_STORE);
        }
        
+       /* recursive filling of operator macro list */
+       if(ot->macro.first) {
+               static wmOperator *motherop= NULL;
+               wmOperatorTypeMacro *otmacro;
+               
+               /* ensure all ops are in execution order in 1 list */
+               if(motherop==NULL) 
+                       motherop= op;
+               
+               for(otmacro= ot->macro.first; otmacro; otmacro= otmacro->next) {
+                       wmOperatorType *otm= WM_operatortype_find(otmacro->idname, 0);
+                       wmOperator *opm= wm_operator_create(wm, otm, otmacro->ptr, NULL);
+                       
+                       BLI_addtail(&motherop->macro, opm);
+                       opm->opm= motherop; /* pointer to mom, for modal() */
+               }
+               
+               motherop= NULL;
+       }
+       
        return op;
 }
 
@@ -345,7 +382,7 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P
        wmWindowManager *wm= CTX_wm_manager(C);
        int retval= OPERATOR_PASS_THROUGH;
 
-       if(ot->poll==NULL || ot->poll(C)) {
+       if(wm_operator_poll(C, ot)) {
                wmOperator *op= wm_operator_create(wm, ot, properties, NULL);
                
                if((G.f & G_DEBUG) && event && event->type!=MOUSEMOVE)
@@ -809,7 +846,6 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa
                case EVT_FILESELECT_OPEN: 
                case EVT_FILESELECT_FULL_OPEN: 
                        {
-                               short flag =0; short display =FILE_SHORTDISPLAY; short filter =0; short sort =FILE_SORT_ALPHA;
                                char *dir= NULL; char *path= RNA_string_get_alloc(handler->op->ptr, "filename", NULL, 0);
                                        
                                if(event->val==EVT_FILESELECT_OPEN)
@@ -1198,7 +1234,17 @@ void WM_event_set_handler_flag(wmEventHandler *handler, int flag)
 wmEventHandler *WM_event_add_modal_handler(bContext *C, ListBase *handlers, wmOperator *op)
 {
        wmEventHandler *handler= MEM_callocN(sizeof(wmEventHandler), "event modal handler");
-       handler->op= op;
+       
+       /* operator was part of macro */
+       if(op->opm) {
+               /* give the mother macro to the handler */
+               handler->op= op->opm;
+               /* mother macro opm becomes the macro element */
+               handler->op->opm= op;
+       }
+       else
+               handler->op= op;
+       
        handler->op_area= CTX_wm_area(C);               /* means frozen screen context for modal handlers! */
        handler->op_region= CTX_wm_region(C);
        
index e25c86ea2fdda8bd768025f34a2b2126c733abdd..2b7a18dc1cfc0038fbc358ec15e0f8fa1bc991a7 100644 (file)
@@ -154,6 +154,134 @@ void WM_operatortype_append_ptr(void (*opfunc)(wmOperatorType*, void*), void *us
        BLI_addtail(&global_ops, ot);
 }
 
+/* ********************* macro operator ******************** */
+
+/* macro exec only runs exec calls */
+static int wm_macro_exec(bContext *C, wmOperator *op)
+{
+       wmOperator *opm;
+       int retval= OPERATOR_FINISHED;
+       
+//     printf("macro exec %s\n", op->type->idname);
+       
+       for(opm= op->macro.first; opm; opm= opm->next) {
+               
+               if(opm->type->exec) {
+//                     printf("macro exec %s\n", opm->type->idname);
+                       retval= opm->type->exec(C, opm);
+               
+                       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)
+{
+       wmOperator *opm;
+       int retval= OPERATOR_FINISHED;
+       
+//     printf("macro invoke %s\n", op->type->idname);
+       
+       for(opm= op->macro.first; 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(!(retval & OPERATOR_FINISHED))
+                       break;
+       }
+       
+//     if(opm)
+//             printf("macro ended not finished\n");
+//     else
+//             printf("macro end\n");
+       
+       
+       return retval;
+}
+
+static int wm_macro_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+//     printf("macro modal %s\n", op->type->idname);
+       
+       if(op->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);
+       }       
+       
+       return OPERATOR_FINISHED;
+}
+
+/* Names have to be static for now */
+wmOperatorType *WM_operatortype_append_macro(char *idname, char *name, int flag)
+{
+       wmOperatorType *ot;
+       
+       if(WM_operatortype_exists(idname)) {
+               printf("Macro error: operator %s exists\n", idname);
+               return NULL;
+       }
+       
+       ot= MEM_callocN(sizeof(wmOperatorType), "operatortype");
+       ot->srna= RNA_def_struct(&BLENDER_RNA, "", "OperatorProperties");
+       
+       ot->idname= idname;
+       ot->name= name;
+       ot->flag= OPTYPE_MACRO | flag;
+       
+       ot->exec= wm_macro_exec;
+       ot->invoke= wm_macro_invoke;
+       ot->modal= wm_macro_modal;
+       ot->poll= NULL;
+       
+       RNA_def_struct_ui_text(ot->srna, ot->name, ot->description ? ot->description:"(undocumented operator)"); // XXX All ops should have a description but for now allow them not to.
+       RNA_def_struct_identifier(ot->srna, ot->idname);
+
+       BLI_addtail(&global_ops, ot);
+
+       return ot;
+}
+
+wmOperatorTypeMacro *WM_operatortype_macro_define(wmOperatorType *ot, const char *idname)
+{
+       wmOperatorTypeMacro *otmacro= MEM_callocN(sizeof(wmOperatorTypeMacro), "wmOperatorTypeMacro");
+       
+       BLI_strncpy(otmacro->idname, idname, OP_MAX_TYPENAME);
+
+       /* do this on first use, since operatordefinitions might have been not done yet */
+//     otmacro->ptr= MEM_callocN(sizeof(PointerRNA), "optype macro ItemPtr");
+//     WM_operator_properties_create(otmacro->ptr, idname);
+       
+       BLI_addtail(&ot->macro, otmacro);
+       
+       return otmacro;
+}
+
+static void wm_operatortype_free_macro(wmOperatorType *ot)
+{
+       wmOperatorTypeMacro *otmacro;
+       
+       for(otmacro= ot->macro.first; otmacro; otmacro= otmacro->next) {
+               if(otmacro->ptr) {
+                       WM_operator_properties_free(otmacro->ptr);
+                       MEM_freeN(otmacro->ptr);
+               }
+       }
+       BLI_freelistN(&ot->macro);
+}
+
+
 int WM_operatortype_remove(const char *idname)
 {
        wmOperatorType *ot = WM_operatortype_find(idname, 0);
@@ -163,6 +291,10 @@ int WM_operatortype_remove(const char *idname)
        
        BLI_remlink(&global_ops, ot);
        RNA_struct_free(&BLENDER_RNA, ot->srna);
+       
+       if(ot->macro.first)
+               wm_operatortype_free_macro(ot);
+       
        MEM_freeN(ot);
 
        return 1;
@@ -348,7 +480,7 @@ static void redo_cb(bContext *C, void *arg_op, void *arg2)
        wmOperator *lastop= arg_op;
        
        if(lastop) {
-               ED_undo_pop(C);
+               ED_undo_pop_op(C, lastop);
                WM_operator_repeat(C, lastop);
        }
 }
@@ -1677,6 +1809,12 @@ static void WM_OT_ten_timer(wmOperatorType *ot)
 /* called on initialize WM_exit() */
 void wm_operatortype_free(void)
 {
+       wmOperatorType *ot;
+       
+       for(ot= global_ops.first; ot; ot= ot->next)
+               if(ot->macro.first)
+                       wm_operatortype_free_macro(ot);
+       
        BLI_freelistN(&global_ops);
 }