[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [24732] trunk/blender/source/blender/ windowmanager/intern/wm_operators.c: More macro goodness.

Martin Poirier theeth at yahoo.com
Sat Nov 21 20:49:11 CET 2009


Revision: 24732
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=24732
Author:   theeth
Date:     2009-11-21 20:49:11 +0100 (Sat, 21 Nov 2009)

Log Message:
-----------
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.

Modified Paths:
--------------
    trunk/blender/source/blender/windowmanager/intern/wm_operators.c

Modified: trunk/blender/source/blender/windowmanager/intern/wm_operators.c
===================================================================
--- trunk/blender/source/blender/windowmanager/intern/wm_operators.c	2009-11-21 19:26:02 UTC (rev 24731)
+++ trunk/blender/source/blender/windowmanager/intern/wm_operators.c	2009-11-21 19:49:11 UTC (rev 24732)
@@ -167,65 +167,88 @@
 
 /* ********************* 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 @@
 {
 	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,13 +306,22 @@
 					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 */
 wmOperatorType *WM_operatortype_append_macro(char *idname, char *name, int flag)
 {
@@ -308,6 +342,7 @@
 	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.





More information about the Bf-blender-cvs mailing list