python access to driver namespace, rather then have a textblock defined for drivers...
authorCampbell Barton <ideasman42@gmail.com>
Sat, 27 Nov 2010 02:39:51 +0000 (02:39 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Sat, 27 Nov 2010 02:39:51 +0000 (02:39 +0000)
- 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
source/blender/python/intern/bpy_app.c
source/blender/python/intern/bpy_app.h
source/blender/python/intern/bpy_driver.c
source/blender/windowmanager/intern/wm_files.c
source/blender/windowmanager/intern/wm_init_exit.c
source/creator/creator.c

index 91ca89ac894abed01aacc2b10f48093117c72a97..466d8d3413dc919cb3111e494fa102526f8eef6e 100644 (file)
@@ -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);
index b7a277c76b0af62b48ee27b04ecec9a7c7eec8ed..8977c82dc7c6a00df6cb75aff2f9605cd1fc7caf 100644 (file)
@@ -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 */
 
index 1da5004ee85e5a930f53647525a0c1f8ac1536de..02cadc66f48405d4fe36d060f361df6a60b08282 100644 (file)
@@ -28,4 +28,8 @@
 
 PyObject *BPY_app_struct( void );
 
+/* bpy_driver.c */
+int bpy_pydriver_create_dict(void);
+extern PyObject *bpy_pydriver_Dict;
+
 #endif
index e5719a84fdd258955eb0413b8d6387f962721df5..6de341311be31787bd6b7bb8c2e303037716bf66 100644 (file)
@@ -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);
 
index ba601a65ad5481f037a1a2287fee31d74ec6389f..d2c1a2dc0dc0f2342c099aa1ddef9b2ab46d9a02 100644 (file)
@@ -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
        
index 855317b9f76801d1961cda58d339a7dc1354707a..f75a1c0fb7f089110c38efe3ba80f9c4899ee20c 100644 (file)
@@ -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 */
index 966a36d5625152fe1fc6fdacbd12b5fa096e0e7b..aaa96752cc3a90c1de70a2ab745a11dfe6e85046 100644 (file)
@@ -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