diff options
21 files changed, 360 insertions, 60 deletions
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 795c7585b9c..19b9c315939 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -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); diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 20505356d95..2728aa30e6e 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -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; diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h index 7ccbf1ff18d..7b1c87f9cb2 100644 --- a/source/blender/editors/include/ED_util.h +++ b/source/blender/editors/include/ED_util.h @@ -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); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index da2899dd3b2..6f2b49c0513 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -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); } } diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index 92aa46ea390..34eca8748bc 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -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; } diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 76f355ab7f9..93e91732b2b 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -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; } diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 8ed68d5cd20..edb131d7da2 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -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 */ diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index f34dc2e7c23..5fd5f4ff0ad 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -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; } diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index fe092847183..c1509e78502 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -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); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index f278b717f10..acb3a2257dc 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -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); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 69b297b2e03..c82db3bbe32 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -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); diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c index 1564fcb169b..67d8bc3e5ee 100644 --- a/source/blender/editors/space_view3d/view3d_toolbar.c +++ b/source/blender/editors/space_view3d/view3d_toolbar.c @@ -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); } /* ******************* */ diff --git a/source/blender/editors/util/editmode_undo.c b/source/blender/editors/util/editmode_undo.c index 8484ad78bc4..17a1e0b6cdb 100644 --- a/source/blender/editors/util/editmode_undo.c +++ b/source/blender/editors/util/editmode_undo.c @@ -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) diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c index be04cdecac6..435f2c7ecf4 100644 --- a/source/blender/editors/util/undo.c +++ b/source/blender/editors/util/undo.c @@ -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) diff --git a/source/blender/editors/util/util_intern.h b/source/blender/editors/util/util_intern.h index 37e6c5c25e1..8a0787dde3f 100644 --- a/source/blender/editors/util/util_intern.h +++ b/source/blender/editors/util/util_intern.h @@ -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 */ diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index a7ad502d438..704acbfd52b 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -173,6 +173,18 @@ typedef struct wmWindow { # # +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 { struct wmOperatorType *next, *prev; @@ -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 */ diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 0d3ad96d8c3..f65e5b1b077 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -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); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 3a646c5e799..a083d589d31 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -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 */ diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 863fb3ab4bd..c0ac7b06f5a 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -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); } diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index c75feafe623..33e8a392ba3 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -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); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index e25c86ea2fd..2b7a18dc1cf 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -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); } |