diff options
-rw-r--r-- | blenderplayer/bad_level_call_stubs/stubs.c | 2 | ||||
-rw-r--r-- | release/ui/bpy_ops.py | 28 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_windowmanager_types.h | 4 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_array.c | 6 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_operator.c | 35 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 3 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm.c | 2 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 54 |
8 files changed, 79 insertions, 55 deletions
diff --git a/blenderplayer/bad_level_call_stubs/stubs.c b/blenderplayer/bad_level_call_stubs/stubs.c index 2db012ebcea..5ddafca5340 100644 --- a/blenderplayer/bad_level_call_stubs/stubs.c +++ b/blenderplayer/bad_level_call_stubs/stubs.c @@ -168,7 +168,7 @@ int RE_engine_test_break(struct RenderEngine *engine){return 0;} struct wmOperatorType *WM_operatortype_find(const char *idname, int quiet){return (struct wmOperatorType *) NULL;} struct wmOperatorType *WM_operatortype_first(){return (struct wmOperatorType *) NULL;} struct wmOperatorType *WM_operatortype_exists(const char *idname){return (struct wmOperatorType *) NULL;} -int WM_operator_call_py(struct bContext *C, struct wmOperatorType *ot, struct PointerRNA *properties, struct ReportList *reports){return 0;} +int WM_operator_call_py(struct bContext *C, struct wmOperatorType *ot, int context, struct PointerRNA *properties, struct ReportList *reports){return 0;} int WM_operatortype_remove(const char *idname){return 0;} void WM_operator_properties_free(struct PointerRNA *ptr){} void WM_operator_properties_create(struct PointerRNA *ptr, const char *opstring){} diff --git a/release/ui/bpy_ops.py b/release/ui/bpy_ops.py index aa9bfb460f0..dff8125fca1 100644 --- a/release/ui/bpy_ops.py +++ b/release/ui/bpy_ops.py @@ -5,6 +5,18 @@ from bpy.__ops__ import dir as op_dir from bpy.__ops__ import call as op_call from bpy.__ops__ import get_rna as op_get_rna +# Keep in sync with WM_types.h +context_dict = { + 'INVOKE_DEFAULT':0, + 'INVOKE_REGION_WIN':1, + 'INVOKE_AREA':2, + 'INVOKE_SCREEN':3, + 'EXEC_DEFAULT':4, + 'EXEC_REGION_WIN':5, + 'EXEC_AREA':6, + 'EXEC_SCREEN':7, +} + class bpy_ops(object): ''' Fake module like class. @@ -94,10 +106,22 @@ class bpy_ops_submodule_op(object): # submod.foo -> SUBMOD_OT_foo return self.module.upper() + '_OT_' + self.func - def __call__(self, **kw): + def __call__(self, *args, **kw): # Get the operator from blender - return op_call(self.idname(), kw) + if len(args) > 1: + raise ValueError("only one argument for the execution context is supported ") + + if args: + try: + context = context_dict[args[0]] + except: + raise ValueError("Expected a single context argument in: " + str(list(context_dict.keys()))) + + return op_call(self.idname(), kw, context) + + else: + return op_call(self.idname(), kw) def get_rna(self): ''' diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 7d03bbec1ee..10f83c8b9ec 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -285,6 +285,7 @@ typedef struct wmOperator { ListBase macro; /* list of operators, can be a tree */ struct wmOperator *opm; /* current running macro, not saved */ + short flag, pad[3]; } wmOperator; @@ -295,6 +296,9 @@ typedef struct wmOperator { /* add this flag if the event should pass through */ #define OPERATOR_PASS_THROUGH 8 +/* wmOperator flag */ +#define OPERATOR_REPORT_FREE 1 + /* ************** wmEvent ************************ */ /* for read-only rna access, dont save this */ diff --git a/source/blender/python/intern/bpy_array.c b/source/blender/python/intern/bpy_array.c index d52bfda202d..669cccb7011 100644 --- a/source/blender/python/intern/bpy_array.c +++ b/source/blender/python/intern/bpy_array.c @@ -203,17 +203,17 @@ static void pyrna_py_to_boolean(PyObject *py, char *data) static int py_float_check(PyObject *py) { - return PyFloat_Check(py); + return PyFloat_Check(py) || (PyIndex_Check(py)); } static int py_int_check(PyObject *py) { - return PyLong_Check(py); + return PyLong_Check(py) || (PyIndex_Check(py)); } static int py_bool_check(PyObject *py) { - return PyBool_Check(py); + return PyBool_Check(py) || (PyIndex_Check(py)); } int pyrna_py_to_float_array(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, char *param_data, char *error_str, int error_str_size) diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index e431f2a21e9..062db42e0e9 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -40,42 +40,23 @@ #include "BKE_utildefines.h" -/* 'self' stores the operator string */ static PyObject *pyop_call( PyObject * self, PyObject * args) { wmOperatorType *ot; int error_val = 0; PointerRNA ptr; - char *opname; - PyObject *kw= NULL; + char *opname; + PyObject *kw= NULL; /* optional args */ + + /* note that context is an int, python does the conversion in this case */ + int context= WM_OP_EXEC_DEFAULT; // XXX Todo, work out a better solution for passing on context, could make a tuple from self and pack the name and Context into it... bContext *C = BPy_GetContext(); - - switch(PyTuple_Size(args)) { - case 2: - kw = PyTuple_GET_ITEM(args, 1); - - if(!PyDict_Check(kw)) { - PyErr_SetString( PyExc_AttributeError, "bpy.__ops__.call: expected second arg to be a dict"); - return NULL; - } - /* pass through */ - case 1: - opname = _PyUnicode_AsString(PyTuple_GET_ITEM(args, 0)); - - if(opname==NULL) { - PyErr_SetString( PyExc_AttributeError, "bpy.__ops__.call: expected the first arg to be a string"); - return NULL; - } - break; - default: - PyErr_SetString( PyExc_AttributeError, "bpy.__ops__.call: expected a string and optional dict"); + if (!PyArg_ParseTuple(args, "s|O!i:bpy.__ops__.call", &opname, &PyDict_Type, &kw, &context)) return NULL; - } - ot= WM_operatortype_find(opname, TRUE); @@ -88,7 +69,7 @@ static PyObject *pyop_call( PyObject * self, PyObject * args) PyErr_SetString( PyExc_SystemError, "bpy.__ops__.call: operator poll() function failed, context is incorrect"); return NULL; } - + /* WM_operator_properties_create(&ptr, opname); */ /* Save another lookup */ RNA_pointer_create(NULL, ot->srna, NULL, &ptr); @@ -102,7 +83,7 @@ static PyObject *pyop_call( PyObject * self, PyObject * args) BKE_reports_init(&reports, RPT_STORE); - WM_operator_call_py(C, ot, &ptr, &reports); + WM_operator_call_py(C, ot, context, &ptr, &reports); if(BPy_reports_to_error(&reports)) error_val = -1; diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 0f5558382c4..544804b26d6 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -165,7 +165,7 @@ wmOperatorTypeMacro *WM_operatortype_macro_define(wmOperatorType *ot, const char 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); -int WM_operator_call_py(struct bContext *C, struct wmOperatorType *ot, struct PointerRNA *properties, struct ReportList *reports); +int WM_operator_call_py(struct bContext *C, struct wmOperatorType *ot, int context, struct PointerRNA *properties, struct ReportList *reports); void WM_operator_properties_create(struct PointerRNA *ptr, const char *opstring); void WM_operator_properties_free(struct PointerRNA *ptr); @@ -245,6 +245,5 @@ void WM_jobs_stop_all(struct wmWindowManager *wm); char *WM_clipboard_text_get(int selection); void WM_clipboard_text_set(char *buf, int selection); - #endif /* WM_API_H */ diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 85f8a647826..fecd5c20a15 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -69,7 +69,7 @@ void WM_operator_free(wmOperator *op) MEM_freeN(op->properties); } - if(op->reports) { + if(op->reports && (op->flag & OPERATOR_REPORT_FREE)) { BKE_reports_clear(op->reports); MEM_freeN(op->reports); } diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 6c34ed6f902..717c2d25261 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -345,11 +345,12 @@ static wmOperator *wm_operator_create(wmWindowManager *wm, wmOperatorType *ot, P /* initialize error reports */ if (reports) { - op->reports= reports; /* must be initialized alredy */ + op->reports= reports; /* must be initialized already */ } else { op->reports= MEM_mallocN(sizeof(ReportList), "wmOperatorReportList"); BKE_reports_init(op->reports, RPT_STORE); + op->flag |= OPERATOR_REPORT_FREE; } /* recursive filling of operator macro list */ @@ -392,13 +393,13 @@ static void wm_region_mouse_co(bContext *C, wmEvent *event) } } -static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, PointerRNA *properties) +static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, PointerRNA *properties, ReportList *reports) { wmWindowManager *wm= CTX_wm_manager(C); int retval= OPERATOR_PASS_THROUGH; if(wm_operator_poll(C, ot)) { - wmOperator *op= wm_operator_create(wm, ot, properties, NULL); + wmOperator *op= wm_operator_create(wm, ot, properties, reports); /* if reports==NULL, theyll be initialized */ if((G.f & G_DEBUG) && event && event->type!=MOUSEMOVE) printf("handle evt %d win %d op %s\n", event?event->type:0, CTX_wm_screen(C)->subwinactive, ot->idname); @@ -442,10 +443,12 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P return retval; } -/* invokes operator in context */ -int WM_operator_name_call(bContext *C, const char *opstring, int context, PointerRNA *properties) +/* WM_operator_name_call is the main accessor function + * this is for python to access since its done the operator lookup + * + * invokes operator in context */ +static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, int context, PointerRNA *properties, ReportList *reports) { - wmOperatorType *ot= WM_operatortype_find(opstring, 0); wmWindow *window= CTX_wm_window(C); wmEvent *event; @@ -473,7 +476,7 @@ int WM_operator_name_call(bContext *C, const char *opstring, int context, Pointe CTX_wm_region_set(C, ar1); } - retval= wm_operator_invoke(C, ot, event, properties); + retval= wm_operator_invoke(C, ot, event, properties, reports); /* set region back */ CTX_wm_region_set(C, ar); @@ -488,7 +491,7 @@ int WM_operator_name_call(bContext *C, const char *opstring, int context, Pointe ARegion *ar= CTX_wm_region(C); CTX_wm_region_set(C, NULL); - retval= wm_operator_invoke(C, ot, event, properties); + retval= wm_operator_invoke(C, ot, event, properties, reports); CTX_wm_region_set(C, ar); return retval; @@ -503,7 +506,7 @@ int WM_operator_name_call(bContext *C, const char *opstring, int context, Pointe CTX_wm_region_set(C, NULL); CTX_wm_area_set(C, NULL); - retval= wm_operator_invoke(C, ot, event, properties); + retval= wm_operator_invoke(C, ot, event, properties, reports); CTX_wm_region_set(C, ar); CTX_wm_area_set(C, area); @@ -512,32 +515,45 @@ int WM_operator_name_call(bContext *C, const char *opstring, int context, Pointe case WM_OP_EXEC_DEFAULT: event= NULL; /* pass on without break */ case WM_OP_INVOKE_DEFAULT: - return wm_operator_invoke(C, ot, event, properties); + return wm_operator_invoke(C, ot, event, properties, reports); } } return 0; } + +/* invokes operator in context */ +int WM_operator_name_call(bContext *C, const char *opstring, int context, PointerRNA *properties) +{ + wmOperatorType *ot= WM_operatortype_find(opstring, 0); + if(ot) + return wm_operator_call_internal(C, ot, context, properties, NULL); + + return 0; +} + /* Similar to WM_operator_name_call called with WM_OP_EXEC_DEFAULT context. - wmOperatorType is used instead of operator name since python alredy has the operator type - poll() must be called by python before this runs. - reports can be passed to this function (so python can report them as exceptions) */ -int WM_operator_call_py(bContext *C, wmOperatorType *ot, PointerRNA *properties, ReportList *reports) +int WM_operator_call_py(bContext *C, wmOperatorType *ot, int context, PointerRNA *properties, ReportList *reports) { - wmWindowManager *wm= CTX_wm_manager(C); - wmOperator *op= wm_operator_create(wm, ot, properties, reports); int retval= OPERATOR_CANCELLED; - + +#if 0 + wmOperator *op; + wmWindowManager *wm= CTX_wm_manager(C); + op= wm_operator_create(wm, ot, properties, reports); + if (op->type->exec) retval= op->type->exec(C, op); else printf("error \"%s\" operator has no exec function, python cannot call it\n", op->type->name); - - if (reports) - op->reports= NULL; /* dont let the operator free reports passed to this function */ - WM_operator_free(op); +#endif + + retval= wm_operator_call_internal(C, ot, context, properties, reports); return retval; } @@ -820,7 +836,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand wmOperatorType *ot= WM_operatortype_find(event->keymap_idname, 0); if(ot) - retval= wm_operator_invoke(C, ot, event, properties); + retval= wm_operator_invoke(C, ot, event, properties, NULL); } if(retval & OPERATOR_PASS_THROUGH) |