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.
This commit is contained in:
Campbell Barton 2010-12-15 04:06:19 +00:00
parent ff6e631c86
commit acd7b81c2d
9 changed files with 98 additions and 69 deletions

@ -192,3 +192,16 @@ for hf in sorted(source_list(base, is_c_header)):
if not is_ignore(hf):
if hf not in global_h:
print("missing_h: ", hf)
# test encoding
import traceback
for files in (global_c, global_h):
for f in sorted(files):
i = 1
try:
for l in open(f, "r", encoding="utf8"):
i += 1
except:
print("Non utf8: %s:%d" % (f, i))
if i > 1:
traceback.print_exc()

@ -855,7 +855,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
* specifies a character code generated by a dead key. A dead key is a key that
* generates a character, such as the umlaut (double-dot), that is combined with
* another character to form a composite character. For example, the umlaut-O
* character (Ù) is generated by typing the dead key for the umlaut character, and
* character (Ù) is generated by typing the dead key for the umlaut character, and
* then typing the O key.
*/
case WM_SYSDEADCHAR:

@ -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);

@ -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};

@ -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);
}

@ -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);
}

@ -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);

@ -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)
{

@ -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);