Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2010-01-29 16:06:50 +0300
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2010-01-29 16:06:50 +0300
commit01ea2175db20e5b2040b427217d8b11bb8b31b09 (patch)
treeb3082104e56dd775df44c3be1e85e87432ac250c /source/blender/windowmanager
parent0621a8e08a6b0130b8f51782f4b75b2fe6a299da (diff)
Fix #20327: uv smart project options can't be tweaked.
Python operators calling C operators would get too many undo pushes, causing redo of the python operator not to work. Now the depth of operator callbacks is counted to detected nested calls, and in that case skip the undo/register here, and only do a single undo/register for the mother operator.
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c149
1 files changed, 95 insertions, 54 deletions
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index f508062f702..dc4eec7f5e6 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -303,9 +303,37 @@ int WM_operator_poll(bContext *C, wmOperatorType *ot)
return 1;
}
+static void wm_operator_finished(bContext *C, wmOperator *op, int repeat)
+{
+ wmWindowManager *wm= CTX_wm_manager(C);
+
+ op->customdata= NULL;
+
+ /* we don't want to do undo pushes for operators that are being
+ called from operators that already do an undo push. usually
+ this will happen for python operators that call C operators */
+ if(wm->op_undo_depth == 0)
+ if(op->type->flag & OPTYPE_UNDO)
+ ED_undo_push_op(C, op);
+
+ if(repeat==0) {
+ if(G.f & G_DEBUG) {
+ char *buf = WM_operator_pystring(C, op->type, op->ptr, 1);
+ BKE_report(CTX_wm_reports(C), RPT_OPERATOR, buf);
+ MEM_freeN(buf);
+ }
+
+ if((wm->op_undo_depth == 0) && (op->type->flag & OPTYPE_REGISTER))
+ wm_operator_register(C, op);
+ else
+ WM_operator_free(op);
+ }
+}
+
/* if repeat is true, it doesn't register again, nor does it free */
static int wm_operator_exec(bContext *C, wmOperator *op, int repeat)
{
+ wmWindowManager *wm= CTX_wm_manager(C);
int retval= OPERATOR_CANCELLED;
if(op==NULL || op->type==NULL)
@@ -314,32 +342,22 @@ static int wm_operator_exec(bContext *C, wmOperator *op, int repeat)
if(0==WM_operator_poll(C, op->type))
return retval;
- if(op->type->exec)
+ if(op->type->exec) {
+ if(op->type->flag & OPTYPE_UNDO)
+ wm->op_undo_depth++;
+
retval= op->type->exec(C, op);
+
+ if(op->type->flag & OPTYPE_UNDO)
+ wm->op_undo_depth--;
+ }
if(retval & (OPERATOR_FINISHED|OPERATOR_CANCELLED))
if(op->reports->list.first)
uiPupMenuReports(C, op->reports);
- if(retval & OPERATOR_FINISHED) {
- op->customdata= NULL;
-
- if(op->type->flag & OPTYPE_UNDO)
- ED_undo_push_op(C, op);
-
- if(repeat==0) {
- if(G.f & G_DEBUG) {
- char *buf = WM_operator_pystring(C, op->type, op->ptr, 1);
- BKE_report(CTX_wm_reports(C), RPT_OPERATOR, buf);
- MEM_freeN(buf);
- }
-
- if((op->type->flag & OPTYPE_REGISTER))
- wm_operator_register(C, op);
- else
- WM_operator_free(op);
- }
- }
+ if(retval & OPERATOR_FINISHED)
+ wm_operator_finished(C, op, repeat);
else if(repeat==0)
WM_operator_free(op);
@@ -472,10 +490,24 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P
if(op->type->invoke && event) {
wm_region_mouse_co(C, event);
+
+ if(op->type->flag & OPTYPE_UNDO)
+ wm->op_undo_depth++;
+
retval= op->type->invoke(C, op, event);
+
+ if(op->type->flag & OPTYPE_UNDO)
+ wm->op_undo_depth--;
}
- else if(op->type->exec)
+ else if(op->type->exec) {
+ if(op->type->flag & OPTYPE_UNDO)
+ wm->op_undo_depth++;
+
retval= op->type->exec(C, op);
+
+ if(op->type->flag & OPTYPE_UNDO)
+ wm->op_undo_depth--;
+ }
else
printf("invalid operator call %s\n", ot->idname); /* debug, important to leave a while, should never happen */
@@ -493,21 +525,7 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P
if(retval & OPERATOR_HANDLED)
; /* do nothing, wm_operator_exec() has been called somewhere */
else if(retval & OPERATOR_FINISHED) {
- op->customdata= NULL;
-
- if(ot->flag & OPTYPE_UNDO)
- ED_undo_push_op(C, op);
-
- if(G.f & G_DEBUG) {
- char *buf = WM_operator_pystring(C, op->type, op->ptr, 1);
- BKE_report(CTX_wm_reports(C), RPT_OPERATOR, buf);
- MEM_freeN(buf);
- }
-
- if((ot->flag & OPTYPE_REGISTER))
- wm_operator_register(C, op);
- else
- WM_operator_free(op);
+ wm_operator_finished(C, op, 0);
}
else if(retval & OPERATOR_RUNNING_MODAL) {
/* grab cursor during blocking modal ops (X11)
@@ -657,8 +675,15 @@ int WM_operator_call_py(bContext *C, wmOperatorType *ot, int context, PointerRNA
wmWindowManager *wm= CTX_wm_manager(C);
op= wm_operator_create(wm, ot, properties, reports);
- if (op->type->exec)
+ if (op->type->exec) {
+ if(op->type->flag & OPTYPE_UNDO)
+ wm->op_undo_depth++;
+
retval= op->type->exec(C, op);
+
+ if(op->type->flag & OPTYPE_UNDO)
+ wm->op_undo_depth--;
+ }
else
printf("error \"%s\" operator has no exec function, python cannot call it\n", op->type->name);
#endif
@@ -721,6 +746,7 @@ static void wm_handler_op_context(bContext *C, wmEventHandler *handler)
void WM_event_remove_handlers(bContext *C, ListBase *handlers)
{
wmEventHandler *handler;
+ wmWindowManager *wm= CTX_wm_manager(C);
/* C is zero on freeing database, modal handlers then already were freed */
while((handler=handlers->first)) {
@@ -733,8 +759,14 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers)
wm_handler_op_context(C, handler);
+ if(handler->op->type->flag & OPTYPE_UNDO)
+ wm->op_undo_depth++;
+
handler->op->type->cancel(C, handler->op);
+ if(handler->op->type->flag & OPTYPE_UNDO)
+ wm->op_undo_depth--;
+
CTX_wm_area_set(C, area);
CTX_wm_region_set(C, region);
}
@@ -926,6 +958,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
if(ot->modal) {
/* we set context to where modal handler came from */
+ wmWindowManager *wm= CTX_wm_manager(C);
ScrArea *area= CTX_wm_area(C);
ARegion *region= CTX_wm_region(C);
@@ -933,8 +966,14 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
wm_region_mouse_co(C, event);
wm_event_modalkeymap(C, op, event);
+ if(ot->flag & OPTYPE_UNDO)
+ wm->op_undo_depth++;
+
retval= ot->modal(C, op, event);
+ if(ot->flag & OPTYPE_UNDO)
+ wm->op_undo_depth--;
+
/* putting back screen context, reval can pass trough after modal failures! */
if((retval & OPERATOR_PASS_THROUGH) || wm_event_always_pass(event)) {
CTX_wm_area_set(C, area);
@@ -956,21 +995,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
}
if(retval & OPERATOR_FINISHED) {
- op->customdata= NULL;
-
- if(ot->flag & OPTYPE_UNDO)
- ED_undo_push_op(C, op);
-
- if(G.f & G_DEBUG) {
- char *buf = WM_operator_pystring(C, op->type, op->ptr, 1);
- BKE_report(CTX_wm_reports(C), RPT_OPERATOR, buf);
- MEM_freeN(buf);
- }
-
- if((ot->flag & OPTYPE_REGISTER))
- wm_operator_register(C, op);
- else
- WM_operator_free(op);
+ wm_operator_finished(C, op, 0);
handler->op= NULL;
}
else if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) {
@@ -1053,6 +1078,7 @@ static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *eve
/* fileselect handlers are only in the window queue, so it's save to switch screens or area types */
static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHandler *handler, wmEvent *event)
{
+ wmWindowManager *wm= CTX_wm_manager(C);
SpaceFile *sfile;
int action= WM_HANDLER_CONTINUE;
@@ -1119,7 +1145,15 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa
uiPupMenuSaveOver(C, handler->op, (path)? path: "");
}
else {
- int retval= handler->op->type->exec(C, handler->op);
+ int retval;
+
+ if(handler->op->type->flag & OPTYPE_UNDO)
+ wm->op_undo_depth++;
+
+ retval= handler->op->type->exec(C, handler->op);
+
+ if(handler->op->type->flag & OPTYPE_UNDO)
+ wm->op_undo_depth--;
if (retval & OPERATOR_FINISHED)
if(G.f & G_DEBUG)
@@ -1144,9 +1178,16 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa
}
}
else {
- if(handler->op->type->cancel)
+ if(handler->op->type->cancel) {
+ if(handler->op->type->flag & OPTYPE_UNDO)
+ wm->op_undo_depth++;
+
handler->op->type->cancel(C, handler->op);
+ if(handler->op->type->flag & OPTYPE_UNDO)
+ wm->op_undo_depth--;
+ }
+
WM_operator_free(handler->op);
}