forked from bartvdbraak/blender
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:
parent
65f279b770
commit
82b0a9e369
@ -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 *************** */
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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,11 +265,23 @@ 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;
|
||||
|
||||
/* 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 */
|
||||
tval = driver_get_variable_value(driver, dvar);
|
||||
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)) { */
|
||||
|
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__ */
|
Loading…
Reference in New Issue
Block a user