[Bf-blender-cvs] [82b0a9e] master: PyDriver support for all RNA property types

Campbell Barton noreply at git.blender.org
Mon Apr 4 23:38:28 CEST 2016


Commit: 82b0a9e36900c8aeb374078bd4cb3a7d7f8295e6
Author: Campbell Barton
Date:   Tue Apr 5 07:02:43 2016 +1000
Branches: master
https://developer.blender.org/rB82b0a9e36900c8aeb374078bd4cb3a7d7f8295e6

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.

===================================================================

M	source/blender/blenkernel/BKE_fcurve.h
M	source/blender/blenkernel/intern/fcurve.c
M	source/blender/python/intern/CMakeLists.txt
M	source/blender/python/intern/bpy_driver.c
A	source/blender/python/intern/bpy_rna_driver.c
A	source/blender/python/intern/bpy_rna_driver.h

===================================================================

diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 3db104a..6643382 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 29da218..11b1bbd 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 fa7c940..2715d2c 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 dd1b4ea..f9c0982 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 0000000..482508a
--- /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 0000000..8deac2e
--- /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__ */




More information about the Bf-blender-cvs mailing list