From 02cc80691d71ea305780655d3b0d4cd4530db9c7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 27 Nov 2010 02:39:51 +0000 Subject: [PATCH] python access to driver namespace, rather then have a textblock defined for drivers allow scripts to add functions directly. - bpy.app.driver_namespace, read-only dictionary, edit in-place. - reset on file load and new file. - on errors the namespace used to be reset, this should not be needed. simple example. def driverFunc(val): return val * val bpy.app.driver_namespace['driverFunc'] = driverFunc ... now all drivers can access this function. --- source/blender/python/BPY_extern.h | 2 +- source/blender/python/intern/bpy_app.c | 29 +++++++++++++++---- source/blender/python/intern/bpy_app.h | 4 +++ source/blender/python/intern/bpy_driver.c | 10 ++----- .../blender/windowmanager/intern/wm_files.c | 4 +++ .../windowmanager/intern/wm_init_exit.c | 2 ++ source/creator/creator.c | 1 + 7 files changed, 38 insertions(+), 14 deletions(-) diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index 91ca89ac894..466d8d3413d 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -118,7 +118,7 @@ extern "C" { // int BPY_do_spacehandlers(struct ScrArea *sa, unsigned short event, // short eventValue, unsigned short space_event); // -// void BPY_pydriver_update(void); + void BPY_reset_driver(void); float BPY_eval_driver(struct ChannelDriver *driver); // int BPY_eval_button(struct bContext *C, const char *expr, double *value); diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index b7a277c76b0..8977c82dc7c 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -159,15 +159,34 @@ static PyObject *bpy_app_tempdir_get(PyObject *UNUSED(self), void *UNUSED(closur return PyC_UnicodeFromByte(btempdir); } -PyGetSetDef bpy_app_debug_getset= {"debug", bpy_app_debug_get, bpy_app_debug_set, "Boolean, set when blender is running in debug mode (started with -d)", NULL}; -PyGetSetDef bpy_app_tempdir_getset= {"tempdir", bpy_app_tempdir_get, NULL, "String, the temp directory used by blender (read-only)", NULL}; +static PyObject *bpy_app_driver_dict_get(PyObject *UNUSED(self), void *UNUSED(closure)) +{ + if (bpy_pydriver_Dict == NULL) + if (bpy_pydriver_create_dict() != 0) { + PyErr_SetString(PyExc_RuntimeError, "bpy.app.driver_namespace failed to create dictionary"); + return NULL; + } + + Py_INCREF(bpy_pydriver_Dict); + return bpy_pydriver_Dict; +} + + +PyGetSetDef bpy_app_getsets[]= { + {"debug", bpy_app_debug_get, bpy_app_debug_set, "Boolean, set when blender is running in debug mode (started with -d)", NULL}, + {"tempdir", bpy_app_tempdir_get, NULL, "String, the temp directory used by blender (read-only)", NULL}, + {"driver_namespace", bpy_app_driver_dict_get, NULL, "Dictionary for drivers namespace, editable in-place, reset on file load (read-only)", NULL}, + {NULL, NULL, NULL, NULL, NULL} +}; static void py_struct_seq_getset_init(void) { /* tricky dynamic members, not to py-spec! */ - - PyDict_SetItemString(BlenderAppType.tp_dict, bpy_app_debug_getset.name, PyDescr_NewGetSet(&BlenderAppType, &bpy_app_debug_getset)); - PyDict_SetItemString(BlenderAppType.tp_dict, bpy_app_tempdir_getset.name, PyDescr_NewGetSet(&BlenderAppType, &bpy_app_tempdir_getset)); + PyGetSetDef *getset; + + for(getset= bpy_app_getsets; getset->name; getset++) { + PyDict_SetItemString(BlenderAppType.tp_dict, getset->name, PyDescr_NewGetSet(&BlenderAppType, getset)); + } } /* end dynamic bpy.app */ diff --git a/source/blender/python/intern/bpy_app.h b/source/blender/python/intern/bpy_app.h index 1da5004ee85..02cadc66f48 100644 --- a/source/blender/python/intern/bpy_app.h +++ b/source/blender/python/intern/bpy_app.h @@ -28,4 +28,8 @@ PyObject *BPY_app_struct( void ); +/* bpy_driver.c */ +int bpy_pydriver_create_dict(void); +extern PyObject *bpy_pydriver_Dict; + #endif diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index e5719a84fdd..6de341311be 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -40,7 +40,7 @@ PyObject *bpy_pydriver_Dict = NULL; /* For faster execution we keep a special dictionary for pydrivers, with * the needed modules and aliases. */ -static int bpy_pydriver_create_dict(void) +int bpy_pydriver_create_dict(void) { PyObject *d, *mod; @@ -103,7 +103,7 @@ static int bpy_pydriver_create_dict(void) * reloading the Blender text module "pydrivers.py", if available, so * updates in it reach pydriver evaluation. */ -void BPY_pydriver_update(void) +void BPY_reset_driver(void) { PyGILState_STATE gilstate; int use_gil= 1; // (PyThreadState_Get()==NULL); @@ -126,12 +126,6 @@ void BPY_pydriver_update(void) /* error return function for BPY_eval_pydriver */ static float pydriver_error(ChannelDriver *driver) { - if (bpy_pydriver_Dict) { /* free the global dict used by pydrivers */ - PyDict_Clear(bpy_pydriver_Dict); - Py_DECREF(bpy_pydriver_Dict); - bpy_pydriver_Dict = NULL; - } - driver->flag |= DRIVER_FLAG_INVALID; /* py expression failed */ fprintf(stderr, "\nError in Driver: The following Python expression failed:\n\t'%s'\n\n", driver->expression); diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index ba601a65ad5..d2c1a2dc0dc 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -319,6 +319,7 @@ void WM_read_file(bContext *C, const char *name, ReportList *reports) #ifdef WITH_PYTHON /* run any texts that were loaded in and flagged as modules */ + BPY_reset_driver(); BPY_load_user_modules(C); #endif CTX_wm_window_set(C, NULL); /* exits queues */ @@ -410,6 +411,9 @@ int WM_read_homefile(bContext *C, wmOperator *op) if(CTX_py_init_get(C)) { /* sync addons, these may have changed from the defaults */ BPY_eval_string(C, "__import__('bpy').utils.addon_reset_all()"); + + BPY_reset_driver(); + BPY_load_user_modules(C); } #endif diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 855317b9f76..f75a1c0fb7f 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -146,6 +146,8 @@ void WM_init(bContext *C, int argc, char **argv) #ifdef WITH_PYTHON BPY_set_context(C); /* necessary evil */ BPY_start_python(argc, argv); + + BPY_reset_driver(); BPY_load_user_modules(C); #else (void)argc; /* unused */ diff --git a/source/creator/creator.c b/source/creator/creator.c index 966a36d5625..aaa96752cc3 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -926,6 +926,7 @@ static int load_file(int UNUSED(argc), char **argv, void *data) /* WM_read_file() runs normally but since we're in background mode do here */ #ifdef WITH_PYTHON /* run any texts that were loaded in and flagged as modules */ + BPY_reset_driver(); BPY_load_user_modules(C); #endif