Py-Driver: add 'self' option
[blender.git] / source / blender / blenkernel / intern / anim_sys.c
index d04b950c0434a3064c0b755ed2d73787350fa0da..0d184b70ce3c49ce70faf291f9d8f00cf45e2e0f 100644 (file)
@@ -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 */