2.5: Python operators now have a working poll() function,
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 18 Sep 2009 13:02:20 +0000 (13:02 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 18 Sep 2009 13:02:20 +0000 (13:02 +0000)
solved by wrapping all polling in WM_operator_poll and
adding a special callback for python.

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

index 491ffe6b9dfb59da6cba77e33fe6726454123409..b8fbe56f01cbd0aaf27c7cfae5df170f466a94c6 100644 (file)
@@ -250,7 +250,6 @@ class EXPORT_OT_ply(bpy.types.Operator):
        ]
        
        def poll(self, context):
-               print("Poll")
                return context.active_object != None
        
        def execute(self, context):
index 2d4b2caa845cb31e50f047d89a65067ba0ecb290..fbc3c859f20f407572eb7608ab36bd9bb2556911 100644 (file)
@@ -597,7 +597,7 @@ void uiEndBlock(const bContext *C, uiBlock *block)
                        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;
                        }
index b27425f958db332be1c4e932b9bb25364ac5ed62..b15ddcfae17c8c0d970130879ab0f6858dbad3ca 100644 (file)
@@ -2064,7 +2064,7 @@ static void operator_search_cb(const bContext *C, void *arg, char *str, uiSearch
        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);
                                
index 46341f53c26672b95ced9c01150291a280c66b3c..e1c6f70bde05873b64a28215cb5c83e400a53654 100644 (file)
@@ -163,7 +163,7 @@ static void view3d_panel_operator_redo(const bContext *C, Panel *pa)
        
        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 @@ static void operator_search_cb(const struct bContext *C, void *arg, char *str, u
        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;
index 67a6b3153e442a356e95ef3a0fed440d9a015e68..ee2b0ab848ff0908a297d6acd5f086c106b2842e 100644 (file)
@@ -228,6 +228,7 @@ typedef struct wmOperatorType {
        /* 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;
 
index 69a7e554452354724264ca94c7626452b3e4d0b3..f2e2dd77e6dc19ef70e7b0e3a48603aecee0f88c 100644 (file)
@@ -65,7 +65,7 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
                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;
        }
index 0a487a8dbe8ae1495179cc8e947fb688a48c0374..bbf657d8ce0fe70d02621b4896aa6b87c70c6153 100644 (file)
@@ -81,9 +81,9 @@ static struct BPY_flag_def pyop_ret_flags[] = {
        
 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 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
                
                
                /* Assign instance attributes from operator properties */
-               {
+               if(op) {
                        const char *arg_name;
 
                        RNA_STRUCT_BEGIN(op->ptr, prop) {
@@ -121,10 +121,12 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
                }
 
                /* 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 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
                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 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
        }
        
        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_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
 
 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 @@ void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata)
        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;
        
index a757deb4a8a300e21a8cd7d62a71d209da0ddae2..69c96d0d89d06b3c3f89397e3736e5b8b2ac7f34 100644 (file)
@@ -162,6 +162,7 @@ wmOperatorType *WM_operatortype_append_macro(char *idname, char *name, int flag)
 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);
index 2a2e0141381abbc7b74adf78619e29b3c370b07c..e570a733d89400d93119d081fd4c457db985e39b 100644 (file)
@@ -259,20 +259,23 @@ void wm_event_do_notifiers(bContext *C)
 
 /* ********************* 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 @@ static int wm_operator_exec(bContext *C, wmOperator *op, int repeat)
        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 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P
        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)
index f31d62967aebba9e7c77f1c7eab113b0aad6928f..a6fc575ce703bae4a18f28b604d0d1bbf5d4ce6d 100644 (file)
@@ -682,7 +682,7 @@ static void operator_search_cb(const struct bContext *C, void *arg, char *str, u
        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);