[Bf-blender-cvs] [98045648ab4] master: Add support for Objects in Drive variable `Rotational Difference`

Germano Cavalcante noreply at git.blender.org
Sat Mar 11 14:44:28 CET 2017


Commit: 98045648ab4907a9843ede70de90ef923229dacc
Author: Germano Cavalcante
Date:   Sat Mar 11 10:43:23 2017 -0300
Branches: master
https://developer.blender.org/rB98045648ab4907a9843ede70de90ef923229dacc

Add support for Objects in Drive variable `Rotational Difference`

Thus it is according to the Manual
https://docs.blender.org/manual/en/dev/animation/drivers/drivers_panel.html#driver-variables

===================================================================

M	source/blender/blenkernel/intern/fcurve.c
M	source/blender/editors/space_graph/graph_buttons.c

===================================================================

diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index c67a61a5aad..2ab6158c98e 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -1240,6 +1240,31 @@ static bPoseChannel *dtar_get_pchan_ptr(ChannelDriver *driver, DriverTarget *dta
 	}
 }
 
+static short driver_check_valid_targets(ChannelDriver *driver, DriverVar *dvar)
+{
+	short valid_targets = 0;
+
+	DRIVER_TARGETS_USED_LOOPER(dvar)
+	{
+		Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
+
+		/* 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;
+			dtar->flag |= DTAR_FLAG_INVALID;
+		}
+		else {
+			/* target seems to be OK now... */
+			dtar->flag &= ~DTAR_FLAG_INVALID;
+			valid_targets++;
+		}
+	}
+	DRIVER_TARGETS_LOOPER_END
+
+	return valid_targets;
+}
+
 /* ......... */
 
 /* evaluate 'single prop' driver variable */
@@ -1252,62 +1277,54 @@ 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, 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 (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;
+	short valid_targets = driver_check_valid_targets(driver, dvar);
+
+	/* make sure we have enough valid targets to use - all or nothing for now... */
+	if (driver_check_valid_targets(driver, dvar) != 2) {
+		if (G.debug & G_DEBUG) {
+			printf("RotDiff DVar: not enough valid targets (n = %d) (a = %p, b = %p)\n",
+			        valid_targets, dvar->targets[0].id, dvar->targets[1].id);
 		}
-		
-		/* stop here... */
 		return 0.0f;
 	}
-	else {
-		dtar1->flag &= ~DTAR_FLAG_INVALID;
-		dtar2->flag &= ~DTAR_FLAG_INVALID;
+
+	float (*mat[2])[4];
+
+	/* NOTE: for now, these are all just worldspace */
+	for (int i = 0; i < 2; i++) {
+		/* get pointer to loc values to store in */
+		DriverTarget *dtar = &dvar->targets[i];
+		Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
+		bPoseChannel *pchan;
+
+		/* 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);
+
+		/* check if object or bone */
+		if (pchan) {
+			/* bone */
+			mat[i] = pchan->pose_mat;
+		}
+		else {
+			/* object */
+			mat[i] = ob->obmat;
+		}
 	}
-	
+
+	float q1[4], q2[4], quat[4], angle;
+
 	/* use the final posed locations */
-	mat4_to_quat(q1, pchan->pose_mat);
-	mat4_to_quat(q2, pchan2->pose_mat);
-	
+	mat4_to_quat(q1, mat[0]);
+	mat4_to_quat(q2, mat[1]);
+
 	invert_qt_normalized(q1);
 	mul_qt_qtqt(quat, q1, q2);
 	angle = 2.0f * (saacos(quat[0]));
 	angle = ABS(angle);
-	
+
 	return (angle > (float)M_PI) ? (float)((2.0f * (float)M_PI) - angle) : (float)(angle);
 }
 
@@ -1317,32 +1334,8 @@ 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;
-	
-	/* 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)
-	{
-		Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
-		
-		/* 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;
-			dtar->flag   |= DTAR_FLAG_INVALID;
-		}
-		else {
-			/* target seems to be OK now... */
-			dtar->flag &= ~DTAR_FLAG_INVALID;
-			valid_targets++;
-		}
-	}
-	DRIVER_TARGETS_LOOPER_END
-	
+	short valid_targets = driver_check_valid_targets(driver, dvar);
+
 	/* 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) {
@@ -1351,8 +1344,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
 		}
 		return 0.0f;
 	}
-	
-	
+
 	/* SECOND PASS: get two location values */
 	/* NOTE: for now, these are all just worldspace */
 	DRIVER_TARGETS_USED_LOOPER(dvar)
@@ -1570,7 +1562,7 @@ static DriverVarTypeInfo dvar_types[MAX_DVAR_TYPES] = {
 	BEGIN_DVAR_TYPEDEF(DVAR_TYPE_ROT_DIFF)
 		dvar_eval_rotDiff,     /* eval callback */
 		2,     /* number of targets used */
-		{"Bone 1", "Bone 2"},     /* UI names for targets */
+		{"Object/Bone 1", "Object/Bone 2"},     /* UI names for targets */
 		{DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY, DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* flags */
 	END_DVAR_TYPEDEF,
 	
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index 516814b63b4..cbb8e98e7e0 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -616,30 +616,31 @@ static void graph_panel_driverVar__rotDiff(uiLayout *layout, ID *id, DriverVar *
 	Object *ob2 = (Object *)dtar2->id;
 	PointerRNA dtar_ptr, dtar2_ptr;
 	uiLayout *col;
-	
+
 	/* initialize RNA pointer to the target */
-	RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); 
-	RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr); 
-	
-	/* Bone 1 */
+	RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr);
+	RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr);
+
+	/* Object 1 */
 	col = uiLayoutColumn(layout, true);
 	uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
-	uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Bone 1"), ICON_NONE);
-	
+	uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Object 1"), ICON_NONE);
+
 	if (dtar->id && GS(dtar->id->name) == ID_OB && ob1->pose) {
 		PointerRNA tar_ptr;
-		
+
 		RNA_pointer_create(dtar->id, &RNA_Pose, ob1->pose, &tar_ptr);
 		uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA);
 	}
-	
+
+	/* Object 2 */
 	col = uiLayoutColumn(layout, true);
 	uiLayoutSetRedAlert(col, (dtar2->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
-	uiItemR(col, &dtar2_ptr, "id", 0, IFACE_("Bone 2"), ICON_NONE);
-		
+	uiItemR(col, &dtar2_ptr, "id", 0, IFACE_("Object 2"), ICON_NONE);
+
 	if (dtar2->id && GS(dtar2->id->name) == ID_OB && ob2->pose) {
 		PointerRNA tar_ptr;
-		
+
 		RNA_pointer_create(dtar2->id, &RNA_Pose, ob2->pose, &tar_ptr);
 		uiItemPointerR(col, &dtar2_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA);
 	}
@@ -658,8 +659,8 @@ static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar *
 	/* initialize RNA pointer to the target */
 	RNA_pointer_create(id, &RNA_DriverTarget, dtar,  &dtar_ptr); 
 	RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr); 
-	
-	/* Bone 1 */
+
+	/* Object 1 */
 	col = uiLayoutColumn(layout, true);
 	uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
 	uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Object 1"), ICON_NONE);
@@ -673,7 +674,8 @@ static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar *
 	
 	uiLayoutSetRedAlert(col, false); /* we can clear it again now - it's only needed when creating the ID/Bone fields */
 	uiItemR(col, &dtar_ptr, "transform_space", 0, NULL, ICON_NONE);
-	
+
+	/* Object 2 */
 	col = uiLayoutColumn(layout, true);
 	uiLayoutSetRedAlert(col, (dtar2->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
 	uiItemR(col, &dtar2_ptr, "id", 0, IFACE_("Object 2"), ICON_NONE);




More information about the Bf-blender-cvs mailing list