[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [23332] trunk/blender: 2.5: Python operators now have a working poll() function,

Brecht Van Lommel brecht at blender.org
Fri Sep 18 15:02:21 CEST 2009


Revision: 23332
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=23332
Author:   blendix
Date:     2009-09-18 15:02:20 +0200 (Fri, 18 Sep 2009)

Log Message:
-----------
2.5: Python operators now have a working poll() function,
solved by wrapping all polling in WM_operator_poll and
adding a special callback for python.

Modified Paths:
--------------
    trunk/blender/release/io/export_ply.py
    trunk/blender/source/blender/editors/interface/interface.c
    trunk/blender/source/blender/editors/interface/interface_templates.c
    trunk/blender/source/blender/editors/space_view3d/view3d_toolbar.c
    trunk/blender/source/blender/makesdna/DNA_windowmanager_types.h
    trunk/blender/source/blender/python/intern/bpy_operator.c
    trunk/blender/source/blender/python/intern/bpy_operator_wrap.c
    trunk/blender/source/blender/windowmanager/WM_api.h
    trunk/blender/source/blender/windowmanager/intern/wm_event_system.c
    trunk/blender/source/blender/windowmanager/intern/wm_operators.c

Modified: trunk/blender/release/io/export_ply.py
===================================================================
--- trunk/blender/release/io/export_ply.py	2009-09-18 12:43:36 UTC (rev 23331)
+++ trunk/blender/release/io/export_ply.py	2009-09-18 13:02:20 UTC (rev 23332)
@@ -250,7 +250,6 @@
 	]
 	
 	def poll(self, context):
-		print("Poll")
 		return context.active_object != None
 	
 	def execute(self, context):

Modified: trunk/blender/source/blender/editors/interface/interface.c
===================================================================
--- trunk/blender/source/blender/editors/interface/interface.c	2009-09-18 12:43:36 UTC (rev 23331)
+++ trunk/blender/source/blender/editors/interface/interface.c	2009-09-18 13:02:20 UTC (rev 23332)
@@ -597,7 +597,7 @@
 			if(but->context)
 				CTX_store_set((bContext*)C, but->context);
 
-			if(ot==NULL || (ot->poll && ot->poll((bContext *)C)==0)) {
+			if(ot == NULL || WM_operator_poll((bContext*)C, ot)==0) {
 				but->flag |= UI_BUT_DISABLED;
 				but->lock = 1;
 			}

Modified: trunk/blender/source/blender/editors/interface/interface_templates.c
===================================================================
--- trunk/blender/source/blender/editors/interface/interface_templates.c	2009-09-18 12:43:36 UTC (rev 23331)
+++ trunk/blender/source/blender/editors/interface/interface_templates.c	2009-09-18 13:02:20 UTC (rev 23332)
@@ -2064,7 +2064,7 @@
 	for(; ot; ot= ot->next) {
 		
 		if(BLI_strcasestr(ot->name, str)) {
-			if(ot->poll==NULL || ot->poll((bContext *)C)) {
+			if(WM_operator_poll((bContext*)C, ot)) {
 				char name[256];
 				int len= strlen(ot->name);
 				

Modified: trunk/blender/source/blender/editors/space_view3d/view3d_toolbar.c
===================================================================
--- trunk/blender/source/blender/editors/space_view3d/view3d_toolbar.c	2009-09-18 12:43:36 UTC (rev 23331)
+++ trunk/blender/source/blender/editors/space_view3d/view3d_toolbar.c	2009-09-18 13:02:20 UTC (rev 23332)
@@ -163,7 +163,7 @@
 	
 	if(op==NULL)
 		return;
-	if(op->type->poll && op->type->poll((bContext *)C)==0)
+	if(WM_operator_poll((bContext*)C, op->type) == 0)
 		return;
 	
 	block= uiLayoutGetBlock(pa->layout);
@@ -208,7 +208,7 @@
 	for(; ot; ot= ot->next) {
 		
 		if(BLI_strcasestr(ot->name, str)) {
-			if(ot->poll==NULL || ot->poll((bContext *)C)) {
+			if(WM_operator_poll((bContext*)C, ot)) {
 				
 				if(0==uiSearchItemAdd(items, ot->name, ot, 0))
 					break;

Modified: trunk/blender/source/blender/makesdna/DNA_windowmanager_types.h
===================================================================
--- trunk/blender/source/blender/makesdna/DNA_windowmanager_types.h	2009-09-18 12:43:36 UTC (rev 23331)
+++ trunk/blender/source/blender/makesdna/DNA_windowmanager_types.h	2009-09-18 13:02:20 UTC (rev 23332)
@@ -228,6 +228,7 @@
 	/* only used for operators defined with python
 	 * use to store pointers to python functions */
 	void *pyop_data;
+	int (*pyop_poll)(struct bContext *, struct wmOperatorType *ot);
 
 } wmOperatorType;
 

Modified: trunk/blender/source/blender/python/intern/bpy_operator.c
===================================================================
--- trunk/blender/source/blender/python/intern/bpy_operator.c	2009-09-18 12:43:36 UTC (rev 23331)
+++ trunk/blender/source/blender/python/intern/bpy_operator.c	2009-09-18 13:02:20 UTC (rev 23332)
@@ -65,7 +65,7 @@
 		return NULL;
 	}
 	
-	if(ot->poll && (ot->poll(C) == FALSE)) {
+	if(WM_operator_poll((bContext*)C, ot) == FALSE) {
 		PyErr_SetString( PyExc_SystemError, "bpy.__ops__.call: operator poll() function failed, context is incorrect");
 		return NULL;
 	}

Modified: trunk/blender/source/blender/python/intern/bpy_operator_wrap.c
===================================================================
--- trunk/blender/source/blender/python/intern/bpy_operator_wrap.c	2009-09-18 12:43:36 UTC (rev 23331)
+++ trunk/blender/source/blender/python/intern/bpy_operator_wrap.c	2009-09-18 13:02:20 UTC (rev 23332)
@@ -81,9 +81,9 @@
 	
 extern void BPY_update_modules( void ); //XXX temp solution
 
-static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *event)
+static int PYTHON_OT_generic(int mode, bContext *C, wmOperatorType *ot, wmOperator *op, wmEvent *event)
 {
-	PyObject *py_class = op->type->pyop_data;
+	PyObject *py_class = ot->pyop_data;
 	PyObject *args;
 	PyObject *ret= NULL, *py_class_instance, *item= NULL;
 	int ret_flag= (mode==PYOP_POLL ? 0:OPERATOR_CANCELLED);
@@ -105,7 +105,7 @@
 		
 		
 		/* Assign instance attributes from operator properties */
-		{
+		if(op) {
 			const char *arg_name;
 
 			RNA_STRUCT_BEGIN(op->ptr, prop) {
@@ -121,10 +121,12 @@
 		}
 
 		/* set operator pointer RNA as instance "__operator__" attribute */
-		RNA_pointer_create(NULL, &RNA_Operator, op, &ptr_operator);
-		py_operator= pyrna_struct_CreatePyObject(&ptr_operator);
-		PyObject_SetAttrString(py_class_instance, "__operator__", py_operator);
-		Py_DECREF(py_operator);
+		if(op) {
+			RNA_pointer_create(NULL, &RNA_Operator, op, &ptr_operator);
+			py_operator= pyrna_struct_CreatePyObject(&ptr_operator);
+			PyObject_SetAttrString(py_class_instance, "__operator__", py_operator);
+			Py_DECREF(py_operator);
+		}
 
 		RNA_pointer_create(NULL, &RNA_Context, C, &ptr_context);
 		
@@ -148,8 +150,7 @@
 		else if (mode==PYOP_POLL) {
 			item= PyObject_GetAttrString(py_class, "poll");
 			args = PyTuple_New(2);
-			//XXX  Todo - wrap context in a useful way, None for now.
-			PyTuple_SET_ITEM(args, 1, Py_None);
+			PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context));
 		}
 		PyTuple_SET_ITEM(args, 0, py_class_instance);
 	
@@ -160,21 +161,24 @@
 	}
 	
 	if (ret == NULL) { /* covers py_class_instance failing too */
-		BPy_errors_to_report(op->reports);
+		if(op)
+			BPy_errors_to_report(op->reports);
 	}
 	else {
 		if (mode==PYOP_POLL) {
 			if (PyBool_Check(ret) == 0) {
 				PyErr_SetString(PyExc_ValueError, "Python poll function return value ");
-				BPy_errors_to_report(op->reports);
+				if(op)
+					BPy_errors_to_report(op->reports);
 			}
 			else {
 				ret_flag= ret==Py_True ? 1:0;
 			}
 			
 		} else if (BPY_flag_from_seq(pyop_ret_flags, ret, &ret_flag) == -1) {
-			 /* the returned value could not be converted into a flag */
-			BPy_errors_to_report(op->reports);
+			/* the returned value could not be converted into a flag */
+			if(op)
+				BPy_errors_to_report(op->reports);
 
 			ret_flag = OPERATOR_CANCELLED;
 		}
@@ -225,19 +229,17 @@
 
 static int PYTHON_OT_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
-	return PYTHON_OT_generic(PYOP_INVOKE, C, op, event);	
+	return PYTHON_OT_generic(PYOP_INVOKE, C, op->type, op, event);	
 }
 
 static int PYTHON_OT_execute(bContext *C, wmOperator *op)
 {
-	return PYTHON_OT_generic(PYOP_EXEC, C, op, NULL);
+	return PYTHON_OT_generic(PYOP_EXEC, C, op->type, op, NULL);
 }
 
-static int PYTHON_OT_poll(bContext *C)
+static int PYTHON_OT_poll(bContext *C, wmOperatorType *ot)
 {
-	// XXX TODO - no way to get the operator type (and therefor class) from the poll function.
-	//return PYTHON_OT_generic(PYOP_POLL, C, NULL, NULL);
-	return 1;
+	return PYTHON_OT_generic(PYOP_POLL, C, ot, NULL, NULL);
 }
 
 void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata)
@@ -270,7 +272,7 @@
 	if (PyObject_HasAttrString(py_class, "execute"))
 		ot->exec= PYTHON_OT_execute;
 	if (PyObject_HasAttrString(py_class, "poll"))
-		ot->poll= PYTHON_OT_poll;
+		ot->pyop_poll= PYTHON_OT_poll;
 	
 	ot->pyop_data= userdata;
 	

Modified: trunk/blender/source/blender/windowmanager/WM_api.h
===================================================================
--- trunk/blender/source/blender/windowmanager/WM_api.h	2009-09-18 12:43:36 UTC (rev 23331)
+++ trunk/blender/source/blender/windowmanager/WM_api.h	2009-09-18 13:02:20 UTC (rev 23332)
@@ -162,6 +162,7 @@
 wmOperatorTypeMacro *WM_operatortype_macro_define(wmOperatorType *ot, const char *idname);
 
 
+int			WM_operator_poll		(struct bContext *C, struct wmOperatorType *ot);
 int			WM_operator_call		(struct bContext *C, struct wmOperator *op);
 int			WM_operator_repeat		(struct bContext *C, struct wmOperator *op);
 int         WM_operator_name_call	(struct bContext *C, const char *opstring, int context, struct PointerRNA *properties);

Modified: trunk/blender/source/blender/windowmanager/intern/wm_event_system.c
===================================================================
--- trunk/blender/source/blender/windowmanager/intern/wm_event_system.c	2009-09-18 12:43:36 UTC (rev 23331)
+++ trunk/blender/source/blender/windowmanager/intern/wm_event_system.c	2009-09-18 13:02:20 UTC (rev 23332)
@@ -259,20 +259,23 @@
 
 /* ********************* operators ******************* */
 
-static int wm_operator_poll(bContext *C, wmOperatorType *ot)
+int WM_operator_poll(bContext *C, wmOperatorType *ot)
 {
 	wmOperatorTypeMacro *otmacro;
 	
 	for(otmacro= ot->macro.first; otmacro; otmacro= otmacro->next) {
 		wmOperatorType *ot= WM_operatortype_find(otmacro->idname, 0);
 		
-		if(0==wm_operator_poll(C, ot))
+		if(0==WM_operator_poll(C, ot))
 			return 0;
 	}
 	
-	if(ot->poll)
+	/* python needs operator type, so we added exception for it */
+	if(ot->pyop_poll)
+		return ot->pyop_poll(C, ot);
+	else if(ot->poll)
 		return ot->poll(C);
-	
+
 	return 1;
 }
 
@@ -284,7 +287,7 @@
 	if(op==NULL || op->type==NULL)
 		return retval;
 	
-	if(0==wm_operator_poll(C, op->type))
+	if(0==WM_operator_poll(C, op->type))
 		return retval;
 	
 	if(op->type->exec)
@@ -397,7 +400,7 @@
 	wmWindowManager *wm= CTX_wm_manager(C);
 	int retval= OPERATOR_PASS_THROUGH;
 
-	if(wm_operator_poll(C, ot)) {
+	if(WM_operator_poll(C, ot)) {
 		wmOperator *op= wm_operator_create(wm, ot, properties, reports); /* if reports==NULL, theyll be initialized */
 		
 		if((G.f & G_DEBUG) && event && event->type!=MOUSEMOVE)

Modified: trunk/blender/source/blender/windowmanager/intern/wm_operators.c
===================================================================
--- trunk/blender/source/blender/windowmanager/intern/wm_operators.c	2009-09-18 12:43:36 UTC (rev 23331)
+++ trunk/blender/source/blender/windowmanager/intern/wm_operators.c	2009-09-18 13:02:20 UTC (rev 23332)
@@ -682,7 +682,7 @@
 	for(; ot; ot= ot->next) {
 		
 		if(BLI_strcasestr(ot->name, str)) {
-			if(ot->poll==NULL || ot->poll((bContext *)C)) {
+			if(WM_operator_poll((bContext*)C, ot)) {
 				char name[256];
 				int len= strlen(ot->name);
 				





More information about the Bf-blender-cvs mailing list