diff options
author | Campbell Barton <ideasman42@gmail.com> | 2016-04-05 00:02:43 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2016-04-05 00:38:57 +0300 |
commit | 82b0a9e36900c8aeb374078bd4cb3a7d7f8295e6 (patch) | |
tree | a3fc9e26f72de53c47de2637e52164a24a875f6f /source/blender | |
parent | 65f279b7705a14ffdbd79f1835504344af40c283 (diff) |
PyDriver support for all RNA property types
Support for driver variables that don't resolve to numbers, eg:
objects, bones, curves... etc.
Without this, Python expressions to access this data needed to use an absolute path from `bpy.data`,
however this is inconvenient, breaks easily (based on naming) and wouldn't set the dependencies correctly.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_fcurve.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/fcurve.c | 65 | ||||
-rw-r--r-- | source/blender/python/intern/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_driver.c | 27 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna_driver.c | 79 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna_driver.h | 33 |
6 files changed, 204 insertions, 6 deletions
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 3db104aea73..664338214bf 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -99,6 +99,10 @@ void driver_variable_name_validate(struct DriverVar *dvar); struct DriverVar *driver_add_new_variable(struct ChannelDriver *driver); float driver_get_variable_value(struct ChannelDriver *driver, struct DriverVar *dvar); +bool driver_get_variable_property( + struct ChannelDriver *driver, struct DriverTarget *dtar, + struct PointerRNA *r_ptr, struct PropertyRNA **r_prop, int *r_index); + float evaluate_driver(struct ChannelDriver *driver, const float evaltime); /* ************** F-Curve Modifiers *************** */ diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 29da218f973..11b1bbd64ac 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1151,6 +1151,71 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar) return value; } +/** + * Same as 'dtar_get_prop_val'. but get the RNA property. + */ +bool driver_get_variable_property( + ChannelDriver *driver, DriverTarget *dtar, + PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index) +{ + PointerRNA id_ptr; + PointerRNA ptr; + PropertyRNA *prop; + ID *id; + int index = -1; + + /* sanity check */ + if (ELEM(NULL, driver, dtar)) + return false; + + id = dtar_id_ensure_proxy_from(dtar->id); + + /* error check for missing pointer... */ + if (id == NULL) { + if (G.debug & G_DEBUG) { + printf("Error: driver has an invalid target to use (path = %s)\n", dtar->rna_path); + } + + driver->flag |= DRIVER_FLAG_INVALID; + dtar->flag |= DTAR_FLAG_INVALID; + return false; + } + + /* get RNA-pointer for the ID-block given in target */ + RNA_id_pointer_create(id, &id_ptr); + + /* get property to read from, and get value as appropriate */ + if (dtar->rna_path == NULL || dtar->rna_path[0] == '\0') { + ptr = PointerRNA_NULL; + prop = NULL; /* ok */ + } + else if (RNA_path_resolve_property_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) { + /* ok */ + } + else { + /* path couldn't be resolved */ + if (G.debug & G_DEBUG) { + printf("Driver Evaluation Error: cannot resolve target for %s -> %s\n", id->name, dtar->rna_path); + } + + ptr = PointerRNA_NULL; + *r_prop = NULL; + *r_index = -1; + + driver->flag |= DRIVER_FLAG_INVALID; + dtar->flag |= DTAR_FLAG_INVALID; + return false; + } + + *r_ptr = ptr; + *r_prop = prop; + *r_index = index; + + /* if we're still here, we should be ok... */ + dtar->flag &= ~DTAR_FLAG_INVALID; + return true; +} + /* Helper function to obtain a pointer to a Pose Channel (for evaluating drivers) */ static bPoseChannel *dtar_get_pchan_ptr(ChannelDriver *driver, DriverTarget *dtar) { diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index fa7c94025f7..2715d2c5992 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -71,6 +71,7 @@ set(SRC bpy_rna_anim.c bpy_rna_array.c bpy_rna_callback.c + bpy_rna_driver.c bpy_rna_id_collection.c bpy_traceback.c bpy_util.c @@ -99,6 +100,7 @@ set(SRC bpy_rna.h bpy_rna_anim.h bpy_rna_callback.h + bpy_rna_driver.h bpy_rna_id_collection.h bpy_traceback.h bpy_util.h diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index dd1b4eae61b..f9c0982a4c3 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -42,10 +42,13 @@ #include "BKE_fcurve.h" #include "BKE_global.h" +#include "bpy_rna_driver.h" /* for pyrna_driver_get_variable_value */ + #include "bpy_driver.h" extern void BPY_update_rna_module(void); +#define USE_RNA_AS_PYOBJECT /* for pydrivers (drivers using one-line Python expressions to express relationships between targets) */ PyObject *bpy_pydriver_Dict = NULL; @@ -262,12 +265,24 @@ float BPY_driver_exec(ChannelDriver *driver, const float evaltime) driver_vars = PyDict_New(); for (dvar = driver->variables.first, i = 0; dvar; dvar = dvar->next) { PyObject *driver_arg = NULL; - float tval = 0.0f; - - /* try to get variable value */ - tval = driver_get_variable_value(driver, dvar); - driver_arg = PyFloat_FromDouble((double)tval); - + + /* support for any RNA data */ +#ifdef USE_RNA_AS_PYOBJECT + if (dvar->type == DVAR_TYPE_SINGLE_PROP) { + driver_arg = pyrna_driver_get_variable_value(driver, &dvar->targets[0]); + + if (driver_arg == NULL) { + driver_arg = PyFloat_FromDouble(0.0); + } + } + else +#endif + { + /* try to get variable value */ + float tval = driver_get_variable_value(driver, dvar); + driver_arg = PyFloat_FromDouble((double)tval); + } + /* try to add to dictionary */ /* if (PyDict_SetItemString(driver_vars, dvar->name, driver_arg)) { */ if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg) < 0) { diff --git a/source/blender/python/intern/bpy_rna_driver.c b/source/blender/python/intern/bpy_rna_driver.c new file mode 100644 index 00000000000..482508a8d85 --- /dev/null +++ b/source/blender/python/intern/bpy_rna_driver.c @@ -0,0 +1,79 @@ +/* + * ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/intern/bpy_rna_driver.c + * \ingroup pythonintern + * + * This file defines utility functions that use the RNA API, from PyDrivers. + */ + +#include <Python.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" + +#include "BKE_fcurve.h" + +#include "RNA_access.h" + +#include "bpy_rna.h" + +#include "bpy_rna_driver.h" /* own include */ + + +/** + * A version of #driver_get_variable_value which returns a PyObject. + */ +PyObject *pyrna_driver_get_variable_value( + struct ChannelDriver *driver, struct DriverTarget *dtar) +{ + PyObject *driver_arg = NULL; + PointerRNA ptr; + PropertyRNA *prop = NULL; + int index; + + if (driver_get_variable_property(driver, dtar, &ptr, &prop, &index)) { + if (prop) { + if (index != -1) { + if (index < RNA_property_array_length(&ptr, prop) && index >= 0) { + /* object, property & index */ + driver_arg = pyrna_array_index(&ptr, prop, index); + } + else { + /* out of range, pass */ + } + } + else { + /* object & property */ + driver_arg = pyrna_prop_to_py(&ptr, prop); + } + } + else { + /* object only */ + driver_arg = pyrna_struct_CreatePyObject(&ptr); + } + } + else { + /* can't resolve path, pass */ + } + + return driver_arg; +} diff --git a/source/blender/python/intern/bpy_rna_driver.h b/source/blender/python/intern/bpy_rna_driver.h new file mode 100644 index 00000000000..8deac2e4384 --- /dev/null +++ b/source/blender/python/intern/bpy_rna_driver.h @@ -0,0 +1,33 @@ +/* + * ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BPY_RNA_DRIVER_H__ +#define __BPY_RNA_DRIVER_H__ + +/** \file blender/python/intern/bpy_rna_driver.h + * \ingroup pythonintern + */ + +struct ChannelDriver; +struct DriverTarget; + +PyObject *pyrna_driver_get_variable_value(struct ChannelDriver *driver, struct DriverTarget *dtar); + +#endif /* __BPY_RNA_DRIVER_H__ */ |