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:
authorMartin Poirier <theeth@yahoo.com>2009-11-21 22:49:11 +0300
committerMartin Poirier <theeth@yahoo.com>2009-11-21 22:49:11 +0300
commit75e82b53497944298fb86e884bf8a7a443b961b9 (patch)
tree04c2941dc36e9a3ca345cb0ab8943093dcec0a6a
parentae7286bbf0f35409074f48356474dbd463bc94f4 (diff)
More macro goodness.
Macros now return finished if at least one operator in the macro finished properly. This is done to correctly insert an undo point. This means that all the macros that combine with transform (extrude, loopcut, rip, duplicate) will correctly insert an undo step when transform is cancelled.
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c99
1 files changed, 67 insertions, 32 deletions
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index e4906bed8e0..beece8c9226 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -167,65 +167,88 @@ void WM_operatortype_append_ptr(void (*opfunc)(wmOperatorType*, void*), void *us
/* ********************* macro operator ******************** */
+typedef struct {
+ int retval;
+} MacroData;
+
+static void wm_macro_start(wmOperator *op)
+{
+ if (op->customdata == NULL) {
+ op->customdata = MEM_callocN(sizeof(MacroData), "MacroData");
+ }
+}
+
+static int wm_macro_end(wmOperator *op, int retval)
+{
+ if (retval & OPERATOR_CANCELLED) {
+ MacroData *md = op->customdata;
+
+ if (md->retval & OPERATOR_FINISHED) {
+ retval |= OPERATOR_FINISHED;
+ retval &= ~OPERATOR_CANCELLED;
+ }
+ }
+
+ /* if modal is ending, free custom data */
+ if (retval & (OPERATOR_FINISHED|OPERATOR_CANCELLED)) {
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ }
+ }
+
+ return retval;
+}
+
/* 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);
-
+ wm_macro_start(op);
+
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 (retval & OPERATOR_FINISHED) {
+ MacroData *md = op->customdata;
+ md->retval = OPERATOR_FINISHED; /* keep in mind that at least one operator finished */
+ } else {
+ break; /* operator didn't finish, end macro */
+ }
}
}
-// if(opm)
-// printf("macro ended not finished\n");
-// else
-// printf("macro end\n");
- return retval;
+ return wm_macro_end(op, retval);
}
int wm_macro_invoke_internal(bContext *C, wmOperator *op, wmEvent *event, wmOperator *opm)
{
int retval= OPERATOR_FINISHED;
-// printf("macro invoke %s\n", op->type->idname);
-
/* start from operator received as argument */
for( ; 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 modal, pass operator flags to macro, they may be needed later */
- if(retval & OPERATOR_RUNNING_MODAL)
- op->flag = opm->flag;
-
- if(!(retval & OPERATOR_FINISHED))
- break;
+ if (retval & OPERATOR_FINISHED) {
+ MacroData *md = op->customdata;
+ md->retval = OPERATOR_FINISHED; /* keep in mind that at least one operator finished */
+ } else {
+ break; /* operator didn't finish, end macro */
+ }
}
-// if(opm)
-// printf("macro ended not finished\n");
-// else
-// printf("macro end\n");
-
-
- return retval;
+ return wm_macro_end(op, retval);
}
static int wm_macro_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
+ wm_macro_start(op);
return wm_macro_invoke_internal(C, op, event, op->macro.first);
}
@@ -233,16 +256,18 @@ static int wm_macro_modal(bContext *C, wmOperator *op, wmEvent *event)
{
wmOperator *opm = op->opm;
int retval= OPERATOR_FINISHED;
-// printf("macro modal %s\n", op->type->idname);
if(opm==NULL)
printf("macro error, calling NULL modal()\n");
else {
-// printf("macro modal %s\n", op->opm->type->idname);
retval = opm->type->modal(C, opm, event);
/* if this one is done but it's not the last operator in the macro */
if ((retval & OPERATOR_FINISHED) && opm->next) {
+ MacroData *md = op->customdata;
+
+ md->retval = OPERATOR_FINISHED; /* keep in mind that at least one operator finished */
+
retval = wm_macro_invoke_internal(C, op, event, opm->next);
/* if new operator is modal and also added its own handler */
@@ -281,11 +306,20 @@ static int wm_macro_modal(bContext *C, wmOperator *op, wmEvent *event)
WM_cursor_grab(CTX_wm_window(C), wrap, FALSE, bounds);
}
}
-
}
- }
-
- return retval;
+ }
+
+ return wm_macro_end(op, retval);
+}
+
+static int wm_macro_cancel(bContext *C, wmOperator *op)
+{
+ /* call cancel on the current modal operator, if any */
+ if (op->opm && op->opm->type->cancel) {
+ op->opm->type->cancel(C, op->opm);
+ }
+
+ return wm_macro_end(op, OPERATOR_CANCELLED);
}
/* Names have to be static for now */
@@ -308,6 +342,7 @@ wmOperatorType *WM_operatortype_append_macro(char *idname, char *name, int flag)
ot->exec= wm_macro_exec;
ot->invoke= wm_macro_invoke;
ot->modal= wm_macro_modal;
+ ot->cancel= wm_macro_cancel;
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.