diff options
author | Campbell Barton <ideasman42@gmail.com> | 2010-12-15 07:06:19 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2010-12-15 07:06:19 +0300 |
commit | acd7b81c2d3fa7828d28c1562fad10663d911783 (patch) | |
tree | 5258424d0be22e177fd8019a295740c882e7cfa6 /source | |
parent | ff6e631c86aa934da09db03e9505d5b060007fac (diff) |
bugfix [#25230] Quick extrude Ctrl-LMB : wrong behaviour of 'RotateSource' option.
Problem is is with operator redo which click-extrude exposed.
Check if redo operator can run, otherwise lock the UI and add a label that the operator doesn't support redo.
This is clunky but IMHO better then failing silently and leaving the user confused.
- Merged redo functions into ED_undo_operator_repeat(), code was duplicated in a few places.
- added WM_operator_repeat_check to check if WM_operator_repeat() can run, avoids an undo call when redo work.
Unrelated changes
- GHOST_SystemWin32.cpp set to utf8 encoding.
- cmake_consistency_check.py now checks source files are utf8.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/editors/include/ED_util.h | 6 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_buttons.c | 22 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_toolbar.c | 41 | ||||
-rw-r--r-- | source/blender/editors/util/undo.c | 52 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 1 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 8 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_operators.c | 22 |
7 files changed, 84 insertions, 68 deletions
diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h index 8d654e4eaa5..2936d63511c 100644 --- a/source/blender/editors/include/ED_util.h +++ b/source/blender/editors/include/ED_util.h @@ -51,6 +51,11 @@ void ED_undo_redo (struct bContext *C); void ED_OT_undo (struct wmOperatorType *ot); void ED_OT_redo (struct wmOperatorType *ot); +int ED_undo_operator_repeat(struct bContext *C, struct wmOperator *op); + /* convenience since UI callbacks use this mostly*/ +void ED_undo_operator_repeat_cb(struct bContext *C, void *arg_op, void *arg_unused); +void ED_undo_operator_repeat_cb_evt(struct bContext *C, void *arg_op, int arg_unused); + /* undo_editmode.c */ void undo_editmode_push(struct bContext *C, const char *name, void * (*getdata)(struct bContext *C), @@ -66,7 +71,6 @@ void undo_editmode_menu (struct bContext *C); void undo_editmode_clear (void); void undo_editmode_step (struct bContext *C, int step); - /* ************** XXX OLD CRUFT WARNING ************* */ void apply_keyb_grid(int shift, int ctrl, float *val, float fac1, float fac2, float fac3, int invert); diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 1c400ee1ff8..0352996484a 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -1392,26 +1392,6 @@ static void view3d_panel_bonesketch_spaces(const bContext *C, Panel *pa) uiBlockEndAlign(block); } -/* op->invoke */ -static void redo_cb(bContext *C, void *arg_op, void *arg2) -{ - wmOperator *lastop= arg_op; - - if(lastop) { - int retval; - - if (G.f & G_DEBUG) - printf("operator redo %s\n", lastop->type->name); - ED_undo_pop(C); - retval= WM_operator_repeat(C, lastop); - if((retval & OPERATOR_FINISHED)==0) { - if (G.f & G_DEBUG) - printf("operator redo failed %s\n", lastop->type->name); - ED_undo_redo(C); - } - } -} - static void view3d_panel_operator_redo(const bContext *C, Panel *pa) { wmWindowManager *wm= CTX_wm_manager(C); @@ -1429,7 +1409,7 @@ static void view3d_panel_operator_redo(const bContext *C, Panel *pa) if(op==NULL) return; - uiBlockSetFunc(block, redo_cb, op, NULL); + uiBlockSetFunc(block, ED_undo_operator_repeat_cb, op, NULL); if(!op->properties) { IDPropertyTemplate val = {0}; diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c index 1064611b84f..a20397aa720 100644 --- a/source/blender/editors/space_view3d/view3d_toolbar.c +++ b/source/blender/editors/space_view3d/view3d_toolbar.c @@ -63,38 +63,6 @@ /* ******************* view3d space & buttons ************** */ - -/* op->exec */ -/* XXX DUPLICATE CODE */ -static void redo_cb(bContext *C, void *arg_op, void *UNUSED(arg2)) -{ - wmOperator *lastop= arg_op; - - if(lastop) { - ARegion *ar= CTX_wm_region(C); - ARegion *ar1= BKE_area_find_region_type(CTX_wm_area(C), RGN_TYPE_WINDOW); - int retval; - - if(ar1) - CTX_wm_region_set(C, ar1); - - if (G.f & G_DEBUG) - printf("operator redo %s\n", lastop->type->name); - - ED_undo_pop_op(C, lastop); - retval= WM_operator_repeat(C, lastop); - - if((retval & OPERATOR_FINISHED)==0) { - if (G.f & G_DEBUG) - printf("operator redo failed %s\n", lastop->type->name); - ED_undo_redo(C); - } - - /* set region back */ - CTX_wm_region_set(C, ar); - } -} - static wmOperator *view3d_last_operator(const bContext *C) { wmWindowManager *wm= CTX_wm_manager(C); @@ -118,6 +86,13 @@ static void view3d_panel_operator_redo_buts(const bContext *C, Panel *pa, wmOper op->properties= IDP_New(IDP_GROUP, val, "wmOperatorProperties"); } + /* poll() on this operator may still fail, at the moment there is no nice feedback when this happens + * just fails silently */ + if(!WM_operator_repeat_check(C, op)) { + uiBlockSetButLock(uiLayoutGetBlock(pa->layout), TRUE, "Operator cannot redo"); + uiItemL(pa->layout, "* Redo Unsupported *", 0); // XXX, could give some nicer feedback or not show redo panel at all? + } + RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); if(op->type->ui) { op->layout= pa->layout; @@ -161,7 +136,7 @@ static void view3d_panel_operator_redo(const bContext *C, Panel *pa) block= uiLayoutGetBlock(pa->layout); - uiBlockSetFunc(block, redo_cb, op, NULL); + uiBlockSetFunc(block, ED_undo_operator_repeat_cb, op, NULL); view3d_panel_operator_redo_operator(C, pa, op); } diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c index f0e8184b991..0165cf5a03d 100644 --- a/source/blender/editors/util/undo.c +++ b/source/blender/editors/util/undo.c @@ -38,6 +38,8 @@ #include "BKE_blender.h" #include "BKE_context.h" +#include "BKE_global.h" +#include "BKE_screen.h" #include "BLI_blenlib.h" #include "BLI_editVert.h" @@ -261,3 +263,53 @@ void ED_OT_redo(wmOperatorType *ot) } +/* ui callbacks should call this rather then calling WM_operator_repeat() themselves */ +int ED_undo_operator_repeat(bContext *C, struct wmOperator *op) +{ + int ret= 0; + + if(op) { + ARegion *ar= CTX_wm_region(C); + ARegion *ar1= BKE_area_find_region_type(CTX_wm_area(C), RGN_TYPE_WINDOW); + + if(ar1) + CTX_wm_region_set(C, ar1); + + if(WM_operator_repeat_check(C, op) && WM_operator_poll(C, op->type)) { + int retval; + + if (G.f & G_DEBUG) + printf("redo_cb: operator redo %s\n", op->type->name); + ED_undo_pop_op(C, op); + retval= WM_operator_repeat(C, op); + if((retval & OPERATOR_FINISHED)==0) { + if (G.f & G_DEBUG) + printf("redo_cb: operator redo failed: %s, return %d\n", op->type->name, retval); + ED_undo_redo(C); + } + else { + ret= 1; + } + } + + /* set region back */ + CTX_wm_region_set(C, ar); + } + else { + if (G.f & G_DEBUG) { + printf("redo_cb: WM_operator_repeat_check returned false %s\n", op->type->name); + } + } + + return ret; +} + +void ED_undo_operator_repeat_cb(bContext *C, void *arg_op, void *UNUSED(arg_unused)) +{ + ED_undo_operator_repeat(C, (wmOperator *)arg_op); +} + +void ED_undo_operator_repeat_cb_evt(bContext *C, void *arg_op, int UNUSED(arg_event)) +{ + ED_undo_operator_repeat(C, (wmOperator *)arg_op); +} diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 3a47e29f553..9c3e19ef4b7 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -221,6 +221,7 @@ int WM_operator_poll (struct bContext *C, struct wmOperatorType *ot); int WM_operator_poll_context(struct bContext *C, struct wmOperatorType *ot, int context); int WM_operator_call (struct bContext *C, struct wmOperator *op); int WM_operator_repeat (struct bContext *C, struct wmOperator *op); +int WM_operator_repeat_check(const struct bContext *C, struct wmOperator *op); int WM_operator_name_call (struct bContext *C, const char *opstring, int context, struct PointerRNA *properties); int WM_operator_call_py(struct bContext *C, struct wmOperatorType *ot, int context, struct PointerRNA *properties, struct ReportList *reports); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 579bac52306..08b50ef9d3f 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -514,6 +514,14 @@ int WM_operator_repeat(bContext *C, wmOperator *op) { return wm_operator_exec(C, op, 1); } +/* TRUE if WM_operator_repeat can run + * simple check for now but may become more involved. + * To be sure the operator can run call WM_operator_poll(C, op->type) also, since this call + * checks if WM_operator_repeat() can run at all, not that it WILL run at any time. */ +int WM_operator_repeat_check(const bContext *UNUSED(C), wmOperator *op) +{ + return op->type->exec != NULL; +} static wmOperator *wm_operator_create(wmWindowManager *wm, wmOperatorType *ot, PointerRNA *properties, ReportList *reports) { diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 9f18f23bdd6..d7c84392a12 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -869,17 +869,6 @@ int WM_operator_winactive(bContext *C) return 1; } -/* op->exec */ -static void redo_cb(bContext *C, void *arg_op, int UNUSED(event)) -{ - wmOperator *lastop= arg_op; - - if(lastop) { - ED_undo_pop_op(C, lastop); - WM_operator_repeat(C, lastop); - } -} - static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) { wmWindowManager *wm= CTX_wm_manager(C); @@ -896,10 +885,10 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN|UI_BLOCK_RET_1|UI_BLOCK_MOVEMOUSE_QUIT); /* if register is not enabled, the operator gets freed on OPERATOR_FINISHED - * ui_apply_but_funcs_after calls redo_cb and crashes */ + * ui_apply_but_funcs_after calls ED_undo_operator_repeate_cb and crashes */ assert(op->type->flag & OPTYPE_REGISTER); - uiBlockSetHandleFunc(block, redo_cb, arg_op); + uiBlockSetHandleFunc(block, ED_undo_operator_repeat_cb_evt, arg_op); if(!op->properties) { IDPropertyTemplate val = {0}; @@ -910,6 +899,13 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, width, 20, style); uiItemL(layout, op->type->name, 0); + /* poll() on this operator may still fail, at the moment there is no nice feedback when this happens + * just fails silently */ + if(!WM_operator_repeat_check(C, op)) { + uiBlockSetButLock(uiLayoutGetBlock(layout), TRUE, "Operator cannot redo"); + uiItemL(layout, "* Redo Unsupported *", 0); // XXX, could give some nicer feedback or not show redo panel at all? + } + if(op->type->ui) { op->layout= layout; op->type->ui((bContext*)C, op); |