Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2016-07-30 09:34:01 +0300
committerCampbell Barton <ideasman42@gmail.com>2016-07-30 09:46:13 +0300
commit4e845e06704bad3c11297ae8e86b400ef80b2a89 (patch)
treee26c66b90934e6230f5c4bc67f3fe7419b199ecf /source
parent362b3bbe58ae378d5e154dd1a27d55d913594a1a (diff)
Py-Driver: add 'self' option
Drivers can use this to refer to the data which the driver is applied to, useful for objects, bones, to avoid having to create a variable pointing to its self.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_animsys.h1
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h6
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c156
-rw-r--r--source/blender/blenkernel/intern/fcurve.c98
-rw-r--r--source/blender/editors/animation/keyframing.c13
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c5
-rw-r--r--source/blender/makesdna/DNA_anim_types.h4
-rw-r--r--source/blender/makesrna/RNA_access.h5
-rw-r--r--source/blender/makesrna/RNA_types.h10
-rw-r--r--source/blender/makesrna/intern/rna_access.c19
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c8
-rw-r--r--source/blender/python/BPY_extern.h3
-rw-r--r--source/blender/python/intern/bpy_driver.c21
-rw-r--r--source/blender/python/intern/bpy_driver.h3
-rw-r--r--source/blender/python/intern/bpy_rna_driver.c5
-rw-r--r--source/blender/python/intern/bpy_rna_driver.h2
16 files changed, 256 insertions, 103 deletions
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index 983f3ce22b8..00ea323f934 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -37,6 +37,7 @@ struct Main;
struct AnimData;
struct KeyingSet;
struct KS_Path;
+struct PathResolvedRNA;
struct bContext;
struct PointerRNA;
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index bb4eb652ae2..3a45097efc5 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -48,6 +48,7 @@ struct AnimData;
struct bAction;
struct BezTriple;
struct StructRNA;
+struct PathResolvedRNA;
struct PointerRNA;
struct PropertyRNA;
@@ -107,7 +108,7 @@ 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 PathResolvedRNA *anim_rna, struct ChannelDriver *driver, const float evaltime);
/* ************** F-Curve Modifiers *************** */
@@ -278,8 +279,9 @@ void correct_bezpart(float v1[2], float v2[2], float v3[2], float v4[2]);
/* evaluate fcurve */
float evaluate_fcurve(struct FCurve *fcu, float evaltime);
+float evaluate_fcurve_driver(struct PathResolvedRNA *anim_rna, struct FCurve *fcu, float evaltime);
/* evaluate fcurve and store value */
-float calculate_fcurve(struct FCurve *fcu, float evaltime);
+float calculate_fcurve(struct PathResolvedRNA *anim_rna, struct FCurve *fcu, float evaltime);
/* ************* F-Curve Samples API ******************** */
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index d04b950c043..0d184b70ce3 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -1482,41 +1482,87 @@ static bool animsys_remap_path(AnimMapper *UNUSED(remap), char *path, char **dst
return false;
}
+static bool animsys_store_rna_setting(
+ PointerRNA *ptr, AnimMapper *remap,
+ /* typically 'fcu->rna_path', 'fcu->array_index' */
+ const char *rna_path, const int array_index,
+ PathResolvedRNA *r_result)
+{
+ bool success = false;
+
+ char *path = NULL;
+ bool free_path;
+
+ /* get path, remapped as appropriate to work in its new environment */
+ free_path = animsys_remap_path(remap, (char *)rna_path, &path);
+
+ /* write value to setting */
+ if (path) {
+ /* get property to write to */
+ if (RNA_path_resolve_property(ptr, path, &r_result->ptr, &r_result->prop)) {
+ if ((ptr->id.data == NULL) || RNA_property_animateable(&r_result->ptr, r_result->prop)) {
+ int array_len = RNA_property_array_length(&r_result->ptr, r_result->prop);
+
+ if (array_len && array_index >= array_len) {
+ if (G.debug & G_DEBUG) {
+ printf("Animato: Invalid array index. ID = '%s', '%s[%d]', array length is %d\n",
+ (ptr && ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>",
+ path, array_index, array_len - 1);
+ }
+ }
+ else {
+ r_result->prop_index = array_len ? array_index : -1;
+ success = true;
+ }
+ }
+ }
+ else {
+ /* failed to get path */
+ /* XXX don't tag as failed yet though, as there are some legit situations (Action Constraint)
+ * where some channels will not exist, but shouldn't lock up Action */
+ if (G.debug & G_DEBUG) {
+ printf("Animato: Invalid path. ID = '%s', '%s[%d]'\n",
+ (ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>",
+ path, array_index);
+ }
+ }
+ }
+
+ /* free temp path-info */
+ if (free_path) {
+ MEM_freeN((void *)path);
+ }
+
+ return success;
+}
+
/* less than 1.0 evaluates to false, use epsilon to avoid float error */
#define ANIMSYS_FLOAT_AS_BOOL(value) ((value) > ((1.0f - FLT_EPSILON)))
/* Write the given value to a setting using RNA, and return success */
-static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_index, float value)
+static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, float value)
{
- PropertyRNA *prop;
- PointerRNA new_ptr;
+ PropertyRNA *prop = anim_rna->prop;
+ PointerRNA new_ptr = anim_rna->ptr;
+ int array_index = anim_rna->prop_index;
//printf("%p %s %i %f\n", ptr, path, array_index, value);
/* get property to write to */
- if (RNA_path_resolve_property(ptr, path, &new_ptr, &prop)) {
+ // if (RNA_path_resolve_property(ptr, path, &new_ptr, &prop))
+ {
/* set value for animatable numerical values only
* HACK: some local F-Curves (e.g. those on NLA Strips) are evaluated
* without an ID provided, which causes the animateable test to fail!
*/
- if (RNA_property_animateable(&new_ptr, prop) || (ptr->id.data == NULL)) {
- int array_len = RNA_property_array_length(&new_ptr, prop);
+ // if (RNA_property_animateable(&new_ptr, prop) || (ptr->id.data == NULL))
+ {
bool written = false;
-
- if (array_len && array_index >= array_len) {
- if (G.debug & G_DEBUG) {
- printf("Animato: Invalid array index. ID = '%s', '%s[%d]', array length is %d\n",
- (ptr && ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>",
- path, array_index, array_len - 1);
- }
-
- return false;
- }
-
+
switch (RNA_property_type(prop)) {
case PROP_BOOLEAN:
- if (array_len) {
+ if (array_index != -1) {
if (RNA_property_boolean_get_index(&new_ptr, prop, array_index) != ANIMSYS_FLOAT_AS_BOOL(value)) {
RNA_property_boolean_set_index(&new_ptr, prop, array_index, ANIMSYS_FLOAT_AS_BOOL(value));
written = true;
@@ -1530,7 +1576,7 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind
}
break;
case PROP_INT:
- if (array_len) {
+ if (array_index != -1) {
if (RNA_property_int_get_index(&new_ptr, prop, array_index) != (int)value) {
RNA_property_int_set_index(&new_ptr, prop, array_index, (int)value);
written = true;
@@ -1544,7 +1590,7 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind
}
break;
case PROP_FLOAT:
- if (array_len) {
+ if (array_index != -1) {
if (RNA_property_float_get_index(&new_ptr, prop, array_index) != value) {
RNA_property_float_set_index(&new_ptr, prop, array_index, value);
written = true;
@@ -1606,37 +1652,18 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind
/* successful */
return true;
}
- else {
- /* failed to get path */
- /* XXX don't tag as failed yet though, as there are some legit situations (Action Constraint)
- * where some channels will not exist, but shouldn't lock up Action */
- if (G.debug & G_DEBUG) {
- printf("Animato: Invalid path. ID = '%s', '%s[%d]'\n",
- (ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>",
- path, array_index);
- }
- return false;
- }
}
/* Simple replacement based data-setting of the FCurve using RNA */
bool BKE_animsys_execute_fcurve(PointerRNA *ptr, AnimMapper *remap, FCurve *fcu, float curval)
{
- char *path = NULL;
- bool free_path = false;
+ PathResolvedRNA anim_rna;
bool ok = false;
-
- /* get path, remapped as appropriate to work in its new environment */
- free_path = animsys_remap_path(remap, fcu->rna_path, &path);
-
- /* write value to setting */
- if (path)
- ok = animsys_write_rna_setting(ptr, path, fcu->array_index, curval);
-
- /* free temp path-info */
- if (free_path)
- MEM_freeN(path);
-
+
+ if (animsys_store_rna_setting(ptr, remap, fcu->rna_path, fcu->array_index, &anim_rna)) {
+ ok = animsys_write_rna_setting(&anim_rna, curval);
+ }
+
/* return whether we were successful */
return ok;
}
@@ -1654,8 +1681,11 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr, ListBase *list, AnimMapper
if ((fcu->grp == NULL) || (fcu->grp->flag & AGRP_MUTED) == 0) {
/* check if this curve should be skipped */
if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) {
- const float curval = calculate_fcurve(fcu, ctime);
- BKE_animsys_execute_fcurve(ptr, remap, fcu, curval);
+ PathResolvedRNA anim_rna;
+ if (animsys_store_rna_setting(ptr, remap, fcu->rna_path, fcu->array_index, &anim_rna)) {
+ const float curval = calculate_fcurve(&anim_rna, fcu, ctime);
+ animsys_write_rna_setting(&anim_rna, curval);
+ }
}
}
}
@@ -1684,8 +1714,12 @@ static void animsys_evaluate_drivers(PointerRNA *ptr, AnimData *adt, float ctime
/* evaluate this using values set already in other places
* NOTE: for 'layering' option later on, we should check if we should remove old value before adding
* new to only be done when drivers only changed */
- const float curval = calculate_fcurve(fcu, ctime);
- ok = BKE_animsys_execute_fcurve(ptr, NULL, fcu, curval);
+
+ PathResolvedRNA anim_rna;
+ if (animsys_store_rna_setting(ptr, NULL, fcu->rna_path, fcu->array_index, &anim_rna)) {
+ const float curval = calculate_fcurve(&anim_rna, fcu, ctime);
+ ok = animsys_write_rna_setting(&anim_rna, curval);
+ }
/* clear recalc flag */
driver->flag &= ~DRIVER_FLAG_RECALC;
@@ -1753,8 +1787,11 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup *
for (fcu = agrp->channels.first; (fcu) && (fcu->grp == agrp); fcu = fcu->next) {
/* check if this curve should be skipped */
if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) {
- const float curval = calculate_fcurve(fcu, ctime);
- BKE_animsys_execute_fcurve(ptr, remap, fcu, curval);
+ PathResolvedRNA anim_rna;
+ if (animsys_store_rna_setting(ptr, remap, fcu->rna_path, fcu->array_index, &anim_rna)) {
+ const float curval = calculate_fcurve(&anim_rna, fcu, ctime);
+ animsys_write_rna_setting(&anim_rna, curval);
+ }
}
}
}
@@ -2612,8 +2649,12 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt)
AnimOverride *aor;
/* for each override, simply execute... */
- for (aor = adt->overrides.first; aor; aor = aor->next)
- animsys_write_rna_setting(ptr, aor->rna_path, aor->array_index, aor->value);
+ for (aor = adt->overrides.first; aor; aor = aor->next) {
+ PathResolvedRNA anim_rna;
+ if (animsys_store_rna_setting(ptr, NULL, aor->rna_path, aor->array_index, &anim_rna)) {
+ animsys_write_rna_setting(&anim_rna, aor->value);
+ }
+ }
}
/* ***************************************** */
@@ -2888,8 +2929,13 @@ void BKE_animsys_eval_driver(EvaluationContext *eval_ctx,
* NOTE: for 'layering' option later on, we should check if we should remove old value before adding
* new to only be done when drivers only changed */
//printf("\told val = %f\n", fcu->curval);
- const float curval = calculate_fcurve(fcu, eval_ctx->ctime);
- ok = BKE_animsys_execute_fcurve(&id_ptr, NULL, fcu, curval);
+
+ PathResolvedRNA anim_rna;
+ if (animsys_store_rna_setting(&id_ptr, NULL, fcu->rna_path, fcu->array_index, &anim_rna)) {
+ const float curval = calculate_fcurve(&anim_rna, fcu, eval_ctx->ctime);
+ ok = animsys_write_rna_setting(&anim_rna, curval);
+ }
+
//printf("\tnew val = %f\n", fcu->curval);
/* clear recalc flag */
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 395161aa6ed..a89d423e7a6 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -1859,7 +1859,7 @@ float driver_get_variable_value(ChannelDriver *driver, DriverVar *dvar)
* - "evaltime" is the frame at which F-Curve is being evaluated
* - has to return a float value
*/
-float evaluate_driver(ChannelDriver *driver, const float evaltime)
+float evaluate_driver(PathResolvedRNA *anim_rna, ChannelDriver *driver, const float evaltime)
{
DriverVar *dvar;
@@ -1944,7 +1944,9 @@ float evaluate_driver(ChannelDriver *driver, const float evaltime)
* - on errors it reports, then returns 0.0f
*/
BLI_mutex_lock(&python_driver_lock);
- driver->curval = BPY_driver_exec(driver, evaltime);
+
+ driver->curval = BPY_driver_exec(anim_rna, driver, evaltime);
+
BLI_mutex_unlock(&python_driver_lock);
}
#else /* WITH_PYTHON*/
@@ -2599,25 +2601,64 @@ static float fcurve_eval_samples(FCurve *fcu, FPoint *fpts, float evaltime)
/* Evaluate and return the value of the given F-Curve at the specified frame ("evaltime")
* Note: this is also used for drivers
*/
-float evaluate_fcurve(FCurve *fcu, float evaltime)
+static float evaluate_fcurve_ex(FCurve *fcu, float evaltime, float cvalue)
{
FModifierStackStorage *storage;
- float cvalue = 0.0f;
float devaltime;
+
+ /* evaluate modifiers which modify time to evaluate the base curve at */
+ storage = evaluate_fmodifiers_storage_new(&fcu->modifiers);
+ devaltime = evaluate_time_fmodifiers(storage, &fcu->modifiers, fcu, cvalue, evaltime);
+
+ /* evaluate curve-data
+ * - 'devaltime' instead of 'evaltime', as this is the time that the last time-modifying
+ * F-Curve modifier on the stack requested the curve to be evaluated at
+ */
+ if (fcu->bezt)
+ cvalue = fcurve_eval_keyframes(fcu, fcu->bezt, devaltime);
+ else if (fcu->fpt)
+ cvalue = fcurve_eval_samples(fcu, fcu->fpt, devaltime);
+
+ /* evaluate modifiers */
+ evaluate_value_fmodifiers(storage, &fcu->modifiers, fcu, &cvalue, devaltime);
+
+ evaluate_fmodifiers_storage_free(storage);
+
+ /* if curve can only have integral values, perform truncation (i.e. drop the decimal part)
+ * here so that the curve can be sampled correctly
+ */
+ if (fcu->flag & FCURVE_INT_VALUES)
+ cvalue = floorf(cvalue + 0.5f);
- /* if there is a driver (only if this F-Curve is acting as 'driver'), evaluate it to find value to use as "evaltime"
+ /* return evaluated value */
+ return cvalue;
+}
+
+float evaluate_fcurve(FCurve *fcu, float evaltime)
+{
+ BLI_assert(fcu->driver == NULL);
+
+ return evaluate_fcurve_ex(fcu, evaltime, 0.0);
+}
+
+float evaluate_fcurve_driver(PathResolvedRNA *anim_rna, FCurve *fcu, float evaltime)
+{
+ BLI_assert(fcu->driver != NULL);
+ float cvalue = 0.0f;
+
+ /* if there is a driver (only if this F-Curve is acting as 'driver'), evaluate it to find value to use as "evaltime"
* since drivers essentially act as alternative input (i.e. in place of 'time') for F-Curves
*/
if (fcu->driver) {
/* evaltime now serves as input for the curve */
- evaltime = evaluate_driver(fcu->driver, evaltime);
-
+ evaltime = evaluate_driver(anim_rna, fcu->driver, evaltime);
+
/* only do a default 1-1 mapping if it's unlikely that anything else will set a value... */
if (fcu->totvert == 0) {
FModifier *fcm;
bool do_linear = true;
-
- /* out-of-range F-Modifiers will block, as will those which just plain overwrite the values
+
+ /* out-of-range F-Modifiers will block, as will those which just plain overwrite the values
* XXX: additive is a bit more dicey; it really depends then if things are in range or not...
*/
for (fcm = fcu->modifiers.first; fcm; fcm = fcm->next) {
@@ -2634,7 +2675,7 @@ float evaluate_fcurve(FCurve *fcu, float evaltime)
do_linear = false;
}
}
-
+
/* only copy over results if none of the modifiers disagreed with this */
if (do_linear) {
cvalue = evaltime;
@@ -2642,36 +2683,11 @@ float evaluate_fcurve(FCurve *fcu, float evaltime)
}
}
- /* evaluate modifiers which modify time to evaluate the base curve at */
- storage = evaluate_fmodifiers_storage_new(&fcu->modifiers);
- devaltime = evaluate_time_fmodifiers(storage, &fcu->modifiers, fcu, cvalue, evaltime);
-
- /* evaluate curve-data
- * - 'devaltime' instead of 'evaltime', as this is the time that the last time-modifying
- * F-Curve modifier on the stack requested the curve to be evaluated at
- */
- if (fcu->bezt)
- cvalue = fcurve_eval_keyframes(fcu, fcu->bezt, devaltime);
- else if (fcu->fpt)
- cvalue = fcurve_eval_samples(fcu, fcu->fpt, devaltime);
-
- /* evaluate modifiers */
- evaluate_value_fmodifiers(storage, &fcu->modifiers, fcu, &cvalue, devaltime);
-
- evaluate_fmodifiers_storage_free(storage);
-
- /* if curve can only have integral values, perform truncation (i.e. drop the decimal part)
- * here so that the curve can be sampled correctly
- */
- if (fcu->flag & FCURVE_INT_VALUES)
- cvalue = floorf(cvalue + 0.5f);
-
- /* return evaluated value */
- return cvalue;
+ return evaluate_fcurve_ex(fcu, evaltime, cvalue);
}
/* Calculate the value of the given F-Curve at the given frame, and set its curval */
-float calculate_fcurve(FCurve *fcu, float evaltime)
+float calculate_fcurve(PathResolvedRNA *anim_rna, FCurve *fcu, float evaltime)
{
/* only calculate + set curval (overriding the existing value) if curve has
* any data which warrants this...
@@ -2680,7 +2696,13 @@ float calculate_fcurve(FCurve *fcu, float evaltime)
list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE))
{
/* calculate and set curval (evaluates driver too if necessary) */
- float curval = evaluate_fcurve(fcu, evaltime);
+ float curval;
+ if (fcu->driver) {
+ curval = evaluate_fcurve_driver(anim_rna, fcu, evaltime);
+ }
+ else {
+ curval = evaluate_fcurve(fcu, evaltime);
+ }
fcu->curval = curval; /* debug display only, not thread safe! */
return curval;
}
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 0c0f54f0179..98be77b491f 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -930,11 +930,18 @@ bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *pr
/* update F-Curve flags to ensure proper behaviour for property type */
update_autoflags_fcurve_direct(fcu, prop);
-
+
/* adjust frame on which to add keyframe */
if ((flag & INSERTKEY_DRIVER) && (fcu->driver)) {
- /* for making it easier to add corrective drivers... */
- cfra = evaluate_driver(fcu->driver, cfra);
+ PathResolvedRNA anim_rna;
+
+ if (RNA_path_resolved_create(&ptr, prop, fcu->array_index, &anim_rna)) {
+ /* for making it easier to add corrective drivers... */
+ cfra = evaluate_driver(&anim_rna, fcu->driver, cfra);
+ }
+ else {
+ cfra = 0.0f;
+ }
}
/* obtain value to give keyframe */
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index a9ab1502e16..4cbf04f9d42 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -812,6 +812,11 @@ static void graph_panel_drivers(const bContext *C, Panel *pa)
}
col = uiLayoutColumn(pa->layout, true);
+
+ if (driver->type == DRIVER_TYPE_PYTHON) {
+ uiItemR(col, &driver_ptr, "use_self", 0, NULL, ICON_NONE);
+ }
+
/* debug setting */
uiItemR(col, &driver_ptr, "show_debug_info", 0, NULL, ICON_NONE);
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index 6bd7b3a4999..31fe8fe563e 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -450,7 +450,9 @@ typedef enum eDriver_Flags {
/* the names are cached so they don't need have python unicode versions created each time */
DRIVER_FLAG_RENAMEVAR = (1<<4),
/* intermediate values of driver should be shown in the UI for debugging purposes */
- DRIVER_FLAG_SHOWDEBUG = (1<<5)
+ DRIVER_FLAG_SHOWDEBUG = (1<<5),
+ /* include 'self' in the drivers namespace. */
+ DRIVER_FLAG_USE_SELF = (1<<6),
} eDriver_Flags;
/* F-Curves -------------------------------------- */
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index c3d25ed2972..e884d769afe 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -715,6 +715,11 @@ void RNA_main_pointer_create(struct Main *main, PointerRNA *r_ptr);
void RNA_id_pointer_create(struct ID *id, PointerRNA *r_ptr);
void RNA_pointer_create(struct ID *id, StructRNA *type, void *data, PointerRNA *r_ptr);
+bool RNA_path_resolved_create(
+ PointerRNA *ptr, struct PropertyRNA *prop,
+ const int prop_index,
+ PathResolvedRNA *r_anim_rna);
+
void RNA_blender_rna_pointer_create(PointerRNA *r_ptr);
void RNA_pointer_recast(PointerRNA *ptr, PointerRNA *r_ptr);
diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h
index 1d5f46a1814..276531992f9 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -64,6 +64,16 @@ typedef struct PropertyPointerRNA {
struct PropertyRNA *prop;
} PropertyPointerRNA;
+/**
+ * Stored result of a RNA path lookup (as used by anim-system)
+ */
+typedef struct PathResolvedRNA {
+ struct PointerRNA ptr;
+ struct PropertyRNA *prop;
+ /* -1 for non-array access */
+ int prop_index;
+} PathResolvedRNA;
+
/* Property */
typedef enum PropertyType {
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 5a93e18a7dd..047e5ea17ab 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -6966,3 +6966,22 @@ bool RNA_struct_equals(PointerRNA *a, PointerRNA *b, eRNAEqualsMode mode)
return equals;
}
+
+bool RNA_path_resolved_create(
+ PointerRNA *ptr, struct PropertyRNA *prop,
+ const int prop_index,
+ PathResolvedRNA *r_anim_rna)
+{
+ int array_len = RNA_property_array_length(ptr, prop);
+
+ if ((array_len == 0) || (prop_index < array_len)) {
+ r_anim_rna->ptr = *ptr;
+ r_anim_rna->prop = prop;
+ r_anim_rna->prop_index = array_len ? prop_index : -1;
+
+ return true;
+ }
+ else {
+ return false;
+ }
+}
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index 5fb581eb74a..08c0f98e45b 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -1600,7 +1600,13 @@ static void rna_def_channeldriver(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", DRIVER_FLAG_SHOWDEBUG);
RNA_def_property_ui_text(prop, "Show Debug Info",
"Show intermediate values for the driver calculations to allow debugging of drivers");
-
+
+ prop = RNA_def_property(srna, "use_self", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", DRIVER_FLAG_USE_SELF);
+ RNA_def_property_ui_text(prop, "Use Self",
+ "Pass 'self' argument to Py-Driver, "
+ "so it can access the data referenced by the driver (object, bone, etc...)");
+
/* State Info (for Debugging) */
prop = RNA_def_property(srna, "is_valid", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", DRIVER_FLAG_INVALID);
diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h
index 4006816e788..3148dab3c50 100644
--- a/source/blender/python/BPY_extern.h
+++ b/source/blender/python/BPY_extern.h
@@ -32,6 +32,7 @@
#ifndef __BPY_EXTERN_H__
#define __BPY_EXTERN_H__
+struct PathResolvedRNA;
struct Text; /* defined in DNA_text_types.h */
struct ID; /* DNA_ID.h */
struct Object; /* DNA_object_types.h */
@@ -85,7 +86,7 @@ void BPY_modules_load_user(struct bContext *C);
void BPY_app_handlers_reset(const short do_all);
void BPY_driver_reset(void);
-float BPY_driver_exec(struct ChannelDriver *driver, const float evaltime);
+float BPY_driver_exec(struct PathResolvedRNA *anim_rna, struct ChannelDriver *driver, const float evaltime);
void BPY_DECREF(void *pyob_ptr); /* Py_DECREF() */
void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr);
diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c
index 65b6bd501ce..2f0c054e381 100644
--- a/source/blender/python/intern/bpy_driver.c
+++ b/source/blender/python/intern/bpy_driver.c
@@ -120,6 +120,22 @@ static void bpy_pydriver_update_dict(const float evaltime)
}
}
+static PyObject *bpy_pydriver_InternStr__self = NULL;
+
+static void bpy_pydriver_update_dict_self(struct PathResolvedRNA *anim_rna)
+{
+ if (bpy_pydriver_InternStr__self == NULL) {
+ bpy_pydriver_InternStr__self = PyUnicode_FromString("self");
+ }
+
+ PyObject *item = pyrna_driver_self_from_anim_rna(anim_rna);
+ PyDict_SetItem(bpy_pydriver_Dict,
+ bpy_pydriver_InternStr__self,
+ item);
+ Py_DECREF(item);
+
+}
+
/* Update function, it gets rid of pydrivers global dictionary, forcing
* BPY_driver_exec to recreate it. This function is used to force
* reloading the Blender text module "pydrivers.py", if available, so
@@ -174,7 +190,7 @@ static void pydriver_error(ChannelDriver *driver)
* now release the GIL on python operator execution instead, using
* PyEval_SaveThread() / PyEval_RestoreThread() so we don't lock up blender.
*/
-float BPY_driver_exec(ChannelDriver *driver, const float evaltime)
+float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, const float evaltime)
{
PyObject *driver_vars = NULL;
PyObject *retval = NULL;
@@ -226,6 +242,9 @@ float BPY_driver_exec(ChannelDriver *driver, const float evaltime)
/* update global namespace */
bpy_pydriver_update_dict(evaltime);
+ if (driver->flag & DRIVER_FLAG_USE_SELF) {
+ bpy_pydriver_update_dict_self(anim_rna);
+ }
if (driver->expr_comp == NULL)
driver->flag |= DRIVER_FLAG_RECOMPILE;
diff --git a/source/blender/python/intern/bpy_driver.h b/source/blender/python/intern/bpy_driver.h
index 1fccec7e1b2..017a6fe89c5 100644
--- a/source/blender/python/intern/bpy_driver.h
+++ b/source/blender/python/intern/bpy_driver.h
@@ -28,12 +28,13 @@
#define __BPY_DRIVER_H__
struct ChannelDriver;
+struct PathResolvedRNA;
int bpy_pydriver_create_dict(void);
extern PyObject *bpy_pydriver_Dict;
/* externals */
-float BPY_driver_exec(struct ChannelDriver *driver, const float evaltime);
+float BPY_driver_exec(struct PathResolvedRNA *anim_rna, struct ChannelDriver *driver, const float evaltime);
void BPY_driver_reset(void);
#endif /* __BPY_DRIVER_H__ */
diff --git a/source/blender/python/intern/bpy_rna_driver.c b/source/blender/python/intern/bpy_rna_driver.c
index 482508a8d85..98fc372f2fc 100644
--- a/source/blender/python/intern/bpy_rna_driver.c
+++ b/source/blender/python/intern/bpy_rna_driver.c
@@ -77,3 +77,8 @@ PyObject *pyrna_driver_get_variable_value(
return driver_arg;
}
+
+PyObject *pyrna_driver_self_from_anim_rna(struct PathResolvedRNA *anim_rna)
+{
+ return pyrna_struct_CreatePyObject(&anim_rna->ptr);
+}
diff --git a/source/blender/python/intern/bpy_rna_driver.h b/source/blender/python/intern/bpy_rna_driver.h
index 8deac2e4384..2021575537d 100644
--- a/source/blender/python/intern/bpy_rna_driver.h
+++ b/source/blender/python/intern/bpy_rna_driver.h
@@ -27,7 +27,9 @@
struct ChannelDriver;
struct DriverTarget;
+struct PathResolvedRNA;
PyObject *pyrna_driver_get_variable_value(struct ChannelDriver *driver, struct DriverTarget *dtar);
+PyObject *pyrna_driver_self_from_anim_rna(struct PathResolvedRNA *anim_rna);
#endif /* __BPY_RNA_DRIVER_H__ */