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.
This commit is contained in:
@@ -99,6 +99,10 @@ void driver_variable_name_validate(struct DriverVar *dvar);
|
|||||||
struct DriverVar *driver_add_new_variable(struct ChannelDriver *driver);
|
struct DriverVar *driver_add_new_variable(struct ChannelDriver *driver);
|
||||||
|
|
||||||
float driver_get_variable_value(struct ChannelDriver *driver, struct DriverVar *dvar);
|
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);
|
float evaluate_driver(struct ChannelDriver *driver, const float evaltime);
|
||||||
|
|
||||||
/* ************** F-Curve Modifiers *************** */
|
/* ************** F-Curve Modifiers *************** */
|
||||||
|
@@ -1151,6 +1151,71 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
|
|||||||
return value;
|
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) */
|
/* Helper function to obtain a pointer to a Pose Channel (for evaluating drivers) */
|
||||||
static bPoseChannel *dtar_get_pchan_ptr(ChannelDriver *driver, DriverTarget *dtar)
|
static bPoseChannel *dtar_get_pchan_ptr(ChannelDriver *driver, DriverTarget *dtar)
|
||||||
{
|
{
|
||||||
|
@@ -71,6 +71,7 @@ set(SRC
|
|||||||
bpy_rna_anim.c
|
bpy_rna_anim.c
|
||||||
bpy_rna_array.c
|
bpy_rna_array.c
|
||||||
bpy_rna_callback.c
|
bpy_rna_callback.c
|
||||||
|
bpy_rna_driver.c
|
||||||
bpy_rna_id_collection.c
|
bpy_rna_id_collection.c
|
||||||
bpy_traceback.c
|
bpy_traceback.c
|
||||||
bpy_util.c
|
bpy_util.c
|
||||||
@@ -99,6 +100,7 @@ set(SRC
|
|||||||
bpy_rna.h
|
bpy_rna.h
|
||||||
bpy_rna_anim.h
|
bpy_rna_anim.h
|
||||||
bpy_rna_callback.h
|
bpy_rna_callback.h
|
||||||
|
bpy_rna_driver.h
|
||||||
bpy_rna_id_collection.h
|
bpy_rna_id_collection.h
|
||||||
bpy_traceback.h
|
bpy_traceback.h
|
||||||
bpy_util.h
|
bpy_util.h
|
||||||
|
@@ -42,10 +42,13 @@
|
|||||||
#include "BKE_fcurve.h"
|
#include "BKE_fcurve.h"
|
||||||
#include "BKE_global.h"
|
#include "BKE_global.h"
|
||||||
|
|
||||||
|
#include "bpy_rna_driver.h" /* for pyrna_driver_get_variable_value */
|
||||||
|
|
||||||
#include "bpy_driver.h"
|
#include "bpy_driver.h"
|
||||||
|
|
||||||
extern void BPY_update_rna_module(void);
|
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) */
|
/* for pydrivers (drivers using one-line Python expressions to express relationships between targets) */
|
||||||
PyObject *bpy_pydriver_Dict = NULL;
|
PyObject *bpy_pydriver_Dict = NULL;
|
||||||
@@ -262,11 +265,23 @@ float BPY_driver_exec(ChannelDriver *driver, const float evaltime)
|
|||||||
driver_vars = PyDict_New();
|
driver_vars = PyDict_New();
|
||||||
for (dvar = driver->variables.first, i = 0; dvar; dvar = dvar->next) {
|
for (dvar = driver->variables.first, i = 0; dvar; dvar = dvar->next) {
|
||||||
PyObject *driver_arg = NULL;
|
PyObject *driver_arg = NULL;
|
||||||
float tval = 0.0f;
|
|
||||||
|
|
||||||
/* try to get variable value */
|
/* support for any RNA data */
|
||||||
tval = driver_get_variable_value(driver, dvar);
|
#ifdef USE_RNA_AS_PYOBJECT
|
||||||
driver_arg = PyFloat_FromDouble((double)tval);
|
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 */
|
/* try to add to dictionary */
|
||||||
/* if (PyDict_SetItemString(driver_vars, dvar->name, driver_arg)) { */
|
/* if (PyDict_SetItemString(driver_vars, dvar->name, driver_arg)) { */
|
||||||
|
79
source/blender/python/intern/bpy_rna_driver.c
Normal file
79
source/blender/python/intern/bpy_rna_driver.c
Normal file
@@ -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;
|
||||||
|
}
|
33
source/blender/python/intern/bpy_rna_driver.h
Normal file
33
source/blender/python/intern/bpy_rna_driver.h
Normal file
@@ -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__ */
|
Reference in New Issue
Block a user