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
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/fcurve.c')
-rw-r--r--source/blender/blenkernel/intern/fcurve.c171
1 files changed, 122 insertions, 49 deletions
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index ec61311d89e..f63eb9f87e3 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -169,7 +169,7 @@ void copy_fcurves(ListBase *dst, ListBase *src)
/* ----------------- Finding F-Curves -------------------------- */
/* high level function to get an fcurve from C without having the rna */
-FCurve *id_data_find_fcurve(ID *id, void *data, StructRNA *type, const char *prop_name, int index, char *driven)
+FCurve *id_data_find_fcurve(ID *id, void *data, StructRNA *type, const char *prop_name, int index, bool *r_driven)
{
/* anim vars */
AnimData *adt = BKE_animdata_from_id(id);
@@ -180,8 +180,8 @@ FCurve *id_data_find_fcurve(ID *id, void *data, StructRNA *type, const char *pro
PropertyRNA *prop;
char *path;
- if (driven)
- *driven = FALSE;
+ if (r_driven)
+ *r_driven = false;
/* only use the current action ??? */
if (ELEM(NULL, adt, adt->action))
@@ -201,8 +201,8 @@ FCurve *id_data_find_fcurve(ID *id, void *data, StructRNA *type, const char *pro
/* if not animated, check if driven */
if ((fcu == NULL) && (adt->drivers.first)) {
fcu = list_find_fcurve(&adt->drivers, path, index);
- if (fcu && driven)
- *driven = TRUE;
+ if (fcu && r_driven)
+ *r_driven = true;
fcu = NULL;
}
@@ -305,11 +305,11 @@ int list_find_data_fcurves(ListBase *dst, ListBase *src, const char *dataPrefix,
return matches;
}
-FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction **action, int *driven)
+FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction **action, bool *r_driven)
{
FCurve *fcu = NULL;
- *driven = 0;
+ *r_driven = false;
/* there must be some RNA-pointer + property combon */
if (prop && ptr->id.data && RNA_property_animateable(ptr, prop)) {
@@ -331,7 +331,7 @@ FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction
fcu = list_find_fcurve(&adt->drivers, path, rnaindex);
if (fcu)
- *driven = 1;
+ *r_driven = true;
}
if (fcu && action)
@@ -354,13 +354,13 @@ FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction
/* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_fcurve)
* Returns the index to insert at (data already at that index will be offset if replace is 0)
*/
-int binarysearch_bezt_index(BezTriple array[], float frame, int arraylen, short *replace)
+int binarysearch_bezt_index(BezTriple array[], float frame, int arraylen, bool *r_replace)
{
int start = 0, end = arraylen;
int loopbreaker = 0, maxloop = arraylen * 2;
/* initialize replace-flag first */
- *replace = 0;
+ *r_replace = false;
/* sneaky optimizations (don't go through searching process if...):
* - keyframe to be added is to be added out of current bounds
@@ -377,7 +377,7 @@ int binarysearch_bezt_index(BezTriple array[], float frame, int arraylen, short
/* 'First' Keyframe (when only one keyframe, this case is used) */
framenum = array[0].vec[1][0];
if (IS_EQT(frame, framenum, BEZT_BINARYSEARCH_THRESH)) {
- *replace = 1;
+ *r_replace = true;
return 0;
}
else if (frame < framenum)
@@ -386,7 +386,7 @@ int binarysearch_bezt_index(BezTriple array[], float frame, int arraylen, short
/* 'Last' Keyframe */
framenum = array[(arraylen - 1)].vec[1][0];
if (IS_EQT(frame, framenum, BEZT_BINARYSEARCH_THRESH)) {
- *replace = 1;
+ *r_replace = true;
return (arraylen - 1);
}
else if (frame > framenum)
@@ -404,7 +404,7 @@ int binarysearch_bezt_index(BezTriple array[], float frame, int arraylen, short
/* check if exactly equal to midpoint */
if (IS_EQT(frame, midfra, BEZT_BINARYSEARCH_THRESH)) {
- *replace = 1;
+ *r_replace = true;
return mid;
}
@@ -500,8 +500,8 @@ short calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, flo
BLI_assert(bezt_last != NULL);
if (include_handles) {
- xminv = MIN3(xminv, bezt_first->vec[0][0], bezt_first->vec[1][0]);
- xmaxv = MAX3(xmaxv, bezt_last->vec[1][0], bezt_last->vec[2][0]);
+ xminv = min_fff(xminv, bezt_first->vec[0][0], bezt_first->vec[1][0]);
+ xmaxv = max_fff(xmaxv, bezt_last->vec[1][0], bezt_last->vec[2][0]);
}
else {
xminv = min_ff(xminv, bezt_first->vec[1][0]);
@@ -517,8 +517,8 @@ short calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, flo
for (bezt = fcu->bezt, i = 0; i < fcu->totvert; bezt++, i++) {
if ((do_sel_only == FALSE) || BEZSELECTED(bezt)) {
if (include_handles) {
- yminv = MIN4(yminv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]);
- ymaxv = MAX4(ymaxv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]);
+ yminv = min_ffff(yminv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]);
+ ymaxv = max_ffff(ymaxv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]);
}
else {
yminv = min_ff(yminv, bezt->vec[1][1]);
@@ -859,7 +859,7 @@ void testhandles_fcurve(FCurve *fcu, const short use_handle)
short flag = 0;
/* flag is initialized as selection status
- * of beztriple control-points (labelled 0,1,2)
+ * of beztriple control-points (labelled 0, 1, 2)
*/
if (bezt->f2 & SELECT) flag |= (1 << 1); // == 2
if (use_handle == FALSE) {
@@ -986,9 +986,9 @@ typedef struct DriverVarTypeInfo {
float (*get_value)(ChannelDriver *driver, DriverVar *dvar);
/* allocation of target slots */
- int num_targets; /* number of target slots required */
+ int num_targets; /* number of target slots required */
const char *target_names[MAX_DRIVER_TARGETS]; /* UI names that should be given to the slots */
- int target_flags[MAX_DRIVER_TARGETS]; /* flags defining the requirements for each slot */
+ short target_flags[MAX_DRIVER_TARGETS]; /* flags defining the requirements for each slot */
} DriverVarTypeInfo;
/* Macro to begin definitions */
@@ -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 */
@@ -1024,11 +1024,13 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
id = dtar_id_ensure_proxy_from(dtar->id);
/* error check for missing pointer... */
- /* TODO: tag the specific target too as having issues */
if (id == NULL) {
- printf("Error: driver has an invalid target to use\n");
- if (G.debug & G_DEBUG) printf("\tpath = %s\n", dtar->rna_path);
+ 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 0.0f;
}
@@ -1039,7 +1041,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 +1056,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 +1087,20 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
break;
}
}
-
}
else {
- if (G.debug & G_DEBUG)
+ /* 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 +1139,45 @@ 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))
- printf("Driver Evaluation Error: Rotational difference failed - first 2 targets invalid\n");
- else if (pchan == NULL)
- printf("Driver Evaluation Error: Rotational difference failed - first target not valid PoseChannel\n");
- else if (pchan2 == NULL)
- printf("Driver Evaluation Error: Rotational difference failed - second target not valid PoseChannel\n");
+ if ((pchan == NULL) && (pchan2 == NULL)) {
+ if (G.debug & G_DEBUG) {
+ printf("Driver Evaluation Error: Rotational difference failed - first 2 targets invalid\n");
+ }
+
+ dtar1->flag |= DTAR_FLAG_INVALID;
+ dtar2->flag |= DTAR_FLAG_INVALID;
+ }
+ else if (pchan == NULL) {
+ if (G.debug & G_DEBUG) {
+ printf("Driver Evaluation Error: Rotational difference failed - first target not valid PoseChannel\n");
+ }
+
+ dtar1->flag |= DTAR_FLAG_INVALID;
+ dtar2->flag &= ~DTAR_FLAG_INVALID;
+ }
+ else if (pchan2 == NULL) {
+ if (G.debug & G_DEBUG) {
+ 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;
}
@@ -1163,22 +1200,53 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
{
float loc1[3] = {0.0f, 0.0f, 0.0f};
float loc2[3] = {0.0f, 0.0f, 0.0f};
+ short valid_targets = 0;
- /* get two location values */
- /* NOTE: for now, these are all just worldspace */
+ /* Perform two passes
+ *
+ * FIRST PASS - to just check that everything works...
+ * NOTE: we use loops here to reduce code duplication, though in practice,
+ * there can only be 2 items or else we run into some problems later
+ */
DRIVER_TARGETS_USED_LOOPER(dvar)
{
- /* get pointer to loc values to store in */
Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
- bPoseChannel *pchan;
- float tmp_loc[3];
/* check if this target has valid data */
if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) {
/* invalid target, so will not have enough targets */
driver->flag |= DRIVER_FLAG_INVALID;
- return 0.0f;
+ dtar->flag |= DTAR_FLAG_INVALID;
+ }
+ else {
+ /* target seems to be OK now... */
+ dtar->flag &= ~DTAR_FLAG_INVALID;
+ valid_targets++;
}
+ }
+ DRIVER_TARGETS_LOOPER_END
+
+ /* make sure we have enough valid targets to use - all or nothing for now... */
+ if (valid_targets < dvar->num_targets) {
+ if (G.debug & G_DEBUG) {
+ printf("LocDiff DVar: not enough valid targets (n = %d) (a = %p, b = %p)\n",
+ valid_targets, dvar->targets[0].id, dvar->targets[1].id);
+ }
+ return 0.0f;
+ }
+
+
+ /* SECOND PASS: get two location values */
+ /* NOTE: for now, these are all just worldspace */
+ DRIVER_TARGETS_USED_LOOPER(dvar)
+ {
+ /* get pointer to loc values to store in */
+ Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
+ bPoseChannel *pchan;
+ float tmp_loc[3];
+
+ /* after the checks above, the targets should be valid here... */
+ BLI_assert((ob != NULL) && (GS(ob->id.name) != ID_OB));
/* try to get posechannel */
pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name);
@@ -1192,7 +1260,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
/* extract transform just like how the constraints do it! */
copy_m4_m4(mat, pchan->pose_mat);
- constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
+ BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
/* ... and from that, we get our transform */
copy_v3_v3(tmp_loc, mat[3]);
@@ -1217,7 +1285,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
/* extract transform just like how the constraints do it! */
copy_m4_m4(mat, ob->obmat);
- constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL);
+ BKE_constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL);
/* ... and from that, we get our transform */
copy_v3_v3(tmp_loc, mat[3]);
@@ -1264,8 +1332,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);
@@ -1288,7 +1361,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
/* just like how the constraints do it! */
copy_m4_m4(mat, pchan->pose_mat);
- constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
+ BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
}
else {
/* specially calculate local matrix, since chan_mat is not valid
@@ -1315,7 +1388,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
/* just like how the constraints do it! */
copy_m4_m4(mat, ob->obmat);
- constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL);
+ BKE_constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL);
}
else {
/* transforms to matrix */
@@ -1458,12 +1531,12 @@ void driver_change_variable_type(DriverVar *dvar, int type)
*/
DRIVER_TARGETS_USED_LOOPER(dvar)
{
- int flags = dvti->target_flags[tarIndex];
+ short flags = dvti->target_flags[tarIndex];
/* 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;
}
@@ -2022,12 +2095,12 @@ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime
}
else {
/* bezier interpolation */
- /* v1,v2 are the first keyframe and its 2nd handle */
+ /* (v1, v2) are the first keyframe and its 2nd handle */
v1[0] = prevbezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
v2[0] = prevbezt->vec[2][0];
v2[1] = prevbezt->vec[2][1];
- /* v3,v4 are the last keyframe's 1st handle + the last keyframe */
+ /* (v3, v4) are the last keyframe's 1st handle + the last keyframe */
v3[0] = bezt->vec[0][0];
v3[1] = bezt->vec[0][1];
v4[0] = bezt->vec[1][0];