[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [25226] trunk/blender/source/blender/ python/intern: split out driver functions into its own file
Campbell Barton
ideasman42 at gmail.com
Tue Dec 8 23:35:03 CET 2009
Revision: 25226
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=25226
Author: campbellbarton
Date: 2009-12-08 23:35:03 +0100 (Tue, 08 Dec 2009)
Log Message:
-----------
split out driver functions into its own file
Modified Paths:
--------------
trunk/blender/source/blender/python/intern/bpy_interface.c
Added Paths:
-----------
trunk/blender/source/blender/python/intern/bpy_driver.c
Added: trunk/blender/source/blender/python/intern/bpy_driver.c
===================================================================
--- trunk/blender/source/blender/python/intern/bpy_driver.c (rev 0)
+++ trunk/blender/source/blender/python/intern/bpy_driver.c 2009-12-08 22:35:03 UTC (rev 25226)
@@ -0,0 +1,237 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Willian P. Germano, Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+/* ****************************************** */
+/* Drivers - PyExpression Evaluation */
+
+#include "DNA_anim_types.h"
+
+#include "BPY_extern.h"
+#include "BKE_fcurve.h"
+
+#include <Python.h>
+
+/* for pydrivers (drivers using one-line Python expressions to express relationships between targets) */
+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)
+{
+ PyObject *d, *mod;
+
+ /* validate namespace for driver evaluation */
+ if (bpy_pydriver_Dict) return -1;
+
+ d = PyDict_New();
+ if (d == NULL)
+ return -1;
+ else
+ bpy_pydriver_Dict = d;
+
+ /* import some modules: builtins, bpy, math, (Blender.noise )*/
+ PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins());
+
+ mod = PyImport_ImportModule("math");
+ if (mod) {
+ PyDict_Merge(d, PyModule_GetDict(mod), 0); /* 0 - dont overwrite existing values */
+
+ /* Only keep for backwards compat! - just import all math into root, they are standard */
+ PyDict_SetItemString(d, "math", mod);
+ PyDict_SetItemString(d, "m", mod);
+ Py_DECREF(mod);
+ }
+
+ /* add bpy to global namespace */
+ mod= PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0);
+ if (mod) {
+ PyDict_SetItemString(bpy_pydriver_Dict, "bpy", mod);
+ Py_DECREF(mod);
+ }
+
+
+#if 0 // non existant yet
+ mod = PyImport_ImportModule("Blender.Noise");
+ if (mod) {
+ PyDict_SetItemString(d, "noise", mod);
+ PyDict_SetItemString(d, "n", mod);
+ Py_DECREF(mod);
+ } else {
+ PyErr_Clear();
+ }
+
+ /* If there's a Blender text called pydrivers.py, import it.
+ * Users can add their own functions to this module.
+ */
+ if (G.f & G_DOSCRIPTLINKS) {
+ mod = importText("pydrivers"); /* can also use PyImport_Import() */
+ if (mod) {
+ PyDict_SetItemString(d, "pydrivers", mod);
+ PyDict_SetItemString(d, "p", mod);
+ Py_DECREF(mod);
+ } else {
+ PyErr_Clear();
+ }
+ }
+#endif // non existant yet
+
+ return 0;
+}
+
+/* Update function, it gets rid of pydrivers global dictionary, forcing
+ * BPY_pydriver_eval to recreate it. This function is used to force
+ * reloading the Blender text module "pydrivers.py", if available, so
+ * updates in it reach pydriver evaluation.
+ */
+void BPY_pydriver_update(void)
+{
+ PyGILState_STATE gilstate = PyGILState_Ensure();
+
+ 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;
+ }
+
+ PyGILState_Release(gilstate);
+
+ return;
+}
+
+/* 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);
+
+ // BPy_errors_to_report(NULL); // TODO - reports
+ PyErr_Print();
+ PyErr_Clear();
+
+ return 0.0f;
+}
+
+/* This evals py driver expressions, 'expr' is a Python expression that
+ * should evaluate to a float number, which is returned.
+ */
+float BPY_pydriver_eval (ChannelDriver *driver)
+{
+ PyObject *driver_vars=NULL;
+ PyObject *retval= NULL;
+ PyGILState_STATE gilstate;
+
+ DriverTarget *dtar;
+ float result = 0.0f; /* default return */
+ char *expr = NULL;
+ short targets_ok= 1;
+
+ /* sanity checks - should driver be executed? */
+ if ((driver == NULL) /*|| (G.f & G_DOSCRIPTLINKS)==0*/)
+ return result;
+
+ /* get the py expression to be evaluated */
+ expr = driver->expression;
+ if ((expr == NULL) || (expr[0]=='\0'))
+ return result;
+
+ gilstate = PyGILState_Ensure();
+
+ /* init global dictionary for py-driver evaluation settings */
+ if (!bpy_pydriver_Dict) {
+ if (bpy_pydriver_create_dict() != 0) {
+ fprintf(stderr, "Pydriver error: couldn't create Python dictionary");
+ PyGILState_Release(gilstate);
+ return result;
+ }
+ }
+
+ /* add target values to a dict that will be used as '__locals__' dict */
+ driver_vars = PyDict_New(); // XXX do we need to decref this?
+ for (dtar= driver->targets.first; dtar; dtar= dtar->next) {
+ PyObject *driver_arg = NULL;
+ float tval = 0.0f;
+
+ /* try to get variable value */
+ tval= driver_get_target_value(driver, dtar);
+ driver_arg= PyFloat_FromDouble((double)tval);
+
+ /* try to add to dictionary */
+ if (PyDict_SetItemString(driver_vars, dtar->name, driver_arg)) {
+ /* this target failed - bad name */
+ if (targets_ok) {
+ /* first one - print some extra info for easier identification */
+ fprintf(stderr, "\nBPY_pydriver_eval() - Error while evaluating PyDriver:\n");
+ targets_ok= 0;
+ }
+
+ fprintf(stderr, "\tBPY_pydriver_eval() - couldn't add variable '%s' to namespace \n", dtar->name);
+ BPy_errors_to_report(NULL); // TODO - reports
+ }
+ }
+
+#if 0 // slow
+ /* execute expression to get a value */
+ retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars);
+#else
+ if(driver->flag & DRIVER_FLAG_RECOMPILE || driver->expr_comp==NULL) {
+ Py_XDECREF(driver->expr_comp);
+ driver->expr_comp= Py_CompileString(expr, "<bpy driver>", Py_eval_input);
+ driver->flag &= ~DRIVER_FLAG_RECOMPILE;
+ }
+ if(driver->expr_comp)
+ retval= PyEval_EvalCode(driver->expr_comp, bpy_pydriver_Dict, driver_vars);
+#endif
+
+ /* decref the driver vars first... */
+ Py_DECREF(driver_vars);
+
+ /* process the result */
+ if (retval == NULL) {
+ result = pydriver_error(driver);
+ PyGILState_Release(gilstate);
+ return result;
+ }
+
+ result = (float)PyFloat_AsDouble(retval);
+ Py_DECREF(retval);
+
+ if ((result == -1) && PyErr_Occurred()) {
+ result = pydriver_error(driver);
+ PyGILState_Release(gilstate);
+ return result;
+ }
+
+ /* all fine, make sure the "invalid expression" flag is cleared */
+ driver->flag &= ~DRIVER_FLAG_INVALID;
+
+ PyGILState_Release(gilstate);
+
+ return result;
+}
Modified: trunk/blender/source/blender/python/intern/bpy_interface.c
===================================================================
--- trunk/blender/source/blender/python/intern/bpy_interface.c 2009-12-08 20:58:23 UTC (rev 25225)
+++ trunk/blender/source/blender/python/intern/bpy_interface.c 2009-12-08 22:35:03 UTC (rev 25226)
@@ -49,7 +49,6 @@
#include "BLI_winstuff.h"
#endif
-#include "DNA_anim_types.h"
#include "DNA_space_types.h"
#include "DNA_text_types.h"
@@ -61,7 +60,6 @@
#include "BLI_string.h"
#include "BKE_context.h"
-#include "BKE_fcurve.h"
#include "BKE_text.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -77,7 +75,6 @@
#include "../generic/BGL.h"
#include "../generic/IDProp.h"
-
/* for internal use, when starting and ending python scripts */
/* incase a python script triggers another python call, stop bpy_context_clear from invalidating */
@@ -617,212 +614,7 @@
#include "PIL_time.h"
#endif
-/* ****************************************** */
-/* Drivers - PyExpression Evaluation */
-/* for pydrivers (drivers using one-line Python expressions to express relationships between targets) */
-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)
-{
- PyObject *d, *mod;
-
- /* validate namespace for driver evaluation */
- if (bpy_pydriver_Dict) return -1;
-
- d = PyDict_New();
- if (d == NULL)
- return -1;
- else
- bpy_pydriver_Dict = d;
-
- /* import some modules: builtins, bpy, math, (Blender.noise )*/
- PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins());
-
- mod = PyImport_ImportModule("math");
- if (mod) {
- PyDict_Merge(d, PyModule_GetDict(mod), 0); /* 0 - dont overwrite existing values */
-
- /* Only keep for backwards compat! - just import all math into root, they are standard */
- PyDict_SetItemString(d, "math", mod);
- PyDict_SetItemString(d, "m", mod);
- Py_DECREF(mod);
- }
-
- /* add bpy to global namespace */
- mod= PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0);
- if (mod) {
- PyDict_SetItemString(bpy_pydriver_Dict, "bpy", mod);
- Py_DECREF(mod);
- }
-
-
-#if 0 // non existant yet
- mod = PyImport_ImportModule("Blender.Noise");
- if (mod) {
- PyDict_SetItemString(d, "noise", mod);
- PyDict_SetItemString(d, "n", mod);
- Py_DECREF(mod);
- } else {
- PyErr_Clear();
- }
-
- /* If there's a Blender text called pydrivers.py, import it.
- * Users can add their own functions to this module.
- */
- if (G.f & G_DOSCRIPTLINKS) {
- mod = importText("pydrivers"); /* can also use PyImport_Import() */
- if (mod) {
- PyDict_SetItemString(d, "pydrivers", mod);
- PyDict_SetItemString(d, "p", mod);
- Py_DECREF(mod);
- } else {
- PyErr_Clear();
- }
- }
-#endif // non existant yet
-
- return 0;
-}
-
-/* Update function, it gets rid of pydrivers global dictionary, forcing
- * BPY_pydriver_eval to recreate it. This function is used to force
- * reloading the Blender text module "pydrivers.py", if available, so
- * updates in it reach pydriver evaluation.
- */
-void BPY_pydriver_update(void)
-{
- PyGILState_STATE gilstate = PyGILState_Ensure();
-
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list