Invalid Driver Targets are now indicated appropriately (using Red Backgrounds)
[blender.git] / source / blender / blenkernel / intern / fcurve.c
index 23f3a3ad3fd1f6a4ca62b0fb6531a55228e3ed95..64480980acdca6f1654a0053f5dc5b77f6bc61e7 100644 (file)
@@ -1014,7 +1014,7 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
        PointerRNA id_ptr, ptr;
        PropertyRNA *prop;
        ID *id;
-       int index;
+       int index = -1;
        float value = 0.0f;
        
        /* sanity check */
@@ -1029,6 +1029,7 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
                printf("Error: driver has an invalid target to use\n");
                if (G.debug & G_DEBUG) printf("\tpath = %s\n", dtar->rna_path);
                driver->flag |= DRIVER_FLAG_INVALID;
+               dtar->flag   |= DTAR_FLAG_INVALID;
                return 0.0f;
        }
        
@@ -1039,7 +1040,7 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
        if (RNA_path_resolve_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) {
                if (RNA_property_array_check(prop)) {
                        /* array */
-                       if (index < RNA_property_array_length(&ptr, prop)) {
+                       if ((index >= 0) && (index < RNA_property_array_length(&ptr, prop))) {
                                switch (RNA_property_type(prop)) {
                                        case PROP_BOOLEAN:
                                                value = (float)RNA_property_boolean_get_index(&ptr, prop, index);
@@ -1054,6 +1055,17 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
                                                break;
                                }
                        }
+                       else {
+                               /* out of bounds */
+                               if (G.debug & G_DEBUG) {
+                                       printf("Driver Evaluation Error: array index is out of bounds for %s -> %s (%d)", 
+                                              id->name, dtar->rna_path, index);
+                               }
+                               
+                               driver->flag |= DRIVER_FLAG_INVALID;
+                               dtar->flag   |= DTAR_FLAG_INVALID;
+                               return 0.0f;
+                       }
                }
                else {
                        /* not an array */
@@ -1074,16 +1086,19 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
                                        break;
                        }
                }
-
        }
        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);
                
                driver->flag |= DRIVER_FLAG_INVALID;
+               dtar->flag   |= DTAR_FLAG_INVALID;
                return 0.0f;
        }
        
+       /* if we're still here, we should be ok... */
+       dtar->flag &= ~DTAR_FLAG_INVALID;
        return value;
 }
 
@@ -1122,25 +1137,39 @@ static float dvar_eval_singleProp(ChannelDriver *driver, DriverVar *dvar)
 /* evaluate 'rotation difference' driver variable */
 static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar)
 {
+       DriverTarget *dtar1 = &dvar->targets[0];
+       DriverTarget *dtar2 = &dvar->targets[1];
        bPoseChannel *pchan, *pchan2;
        float q1[4], q2[4], quat[4], angle;
        
        /* get pose channels, and check if we've got two */
-       pchan = dtar_get_pchan_ptr(driver, &dvar->targets[0]);
-       pchan2 = dtar_get_pchan_ptr(driver, &dvar->targets[1]);
+       pchan  = dtar_get_pchan_ptr(driver, dtar1);
+       pchan2 = dtar_get_pchan_ptr(driver, dtar2);
        
        if (ELEM(NULL, pchan, pchan2)) {
                /* disable this driver, since it doesn't work correctly... */
                driver->flag |= DRIVER_FLAG_INVALID;
                
                /* check what the error was */
-               if ((pchan == NULL) && (pchan2 == NULL))
+               if ((pchan == NULL) && (pchan2 == NULL)) {
                        printf("Driver Evaluation Error: Rotational difference failed - first 2 targets invalid\n");
-               else if (pchan == NULL)
+                       
+                       dtar1->flag |= DTAR_FLAG_INVALID;
+                       dtar2->flag |= DTAR_FLAG_INVALID;
+               }
+               else if (pchan == NULL) {
                        printf("Driver Evaluation Error: Rotational difference failed - first target not valid PoseChannel\n");
-               else if (pchan2 == NULL)
+                       
+                       dtar1->flag |=  DTAR_FLAG_INVALID;
+                       dtar2->flag &= ~DTAR_FLAG_INVALID;
+               }
+               else if (pchan2 == NULL) {
                        printf("Driver Evaluation Error: Rotational difference failed - second target not valid PoseChannel\n");
                        
+                       dtar1->flag &= ~DTAR_FLAG_INVALID;
+                       dtar2->flag |=  DTAR_FLAG_INVALID;
+               }
+               
                /* stop here... */
                return 0.0f;
        }
@@ -1177,8 +1206,13 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
                if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) {
                        /* invalid target, so will not have enough targets */
                        driver->flag |= DRIVER_FLAG_INVALID;
+                       dtar->flag   |= DTAR_FLAG_INVALID;
                        return 0.0f;
                }
+               else {
+                       /* target seems to be OK now... */
+                       dtar->flag &= ~DTAR_FLAG_INVALID;
+               }
                
                /* try to get posechannel */
                pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name);
@@ -1264,8 +1298,13 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
        if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) {
                /* invalid target, so will not have enough targets */
                driver->flag |= DRIVER_FLAG_INVALID;
+               dtar->flag   |= DTAR_FLAG_INVALID;
                return 0.0f;
        }
+       else {
+               /* target should be valid now */
+               dtar->flag &= ~DTAR_FLAG_INVALID;
+       }
        
        /* try to get posechannel */
        pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name);
@@ -1463,7 +1502,7 @@ void driver_change_variable_type(DriverVar *dvar, int type)
                /* store the flags */
                dtar->flag = flags;
                
-               /* object ID types only, or idtype not yet initialized*/
+               /* object ID types only, or idtype not yet initialized */
                if ((flags & DTAR_FLAG_ID_OB_ONLY) || (dtar->idtype == 0))
                        dtar->idtype = ID_OB;
        }