[Bf-blender-cvs] [15b37a4] master: Speedup for constraints update from python script

Sergey Sharybin noreply at git.blender.org
Thu Mar 19 14:33:05 CET 2015


Commit: 15b37a4a4dc8e3684aa53140e7285eb3deaec52b
Author: Sergey Sharybin
Date:   Thu Mar 19 18:28:49 2015 +0500
Branches: master
https://developer.blender.org/rB15b37a4a4dc8e3684aa53140e7285eb3deaec52b

Speedup for constraints update from python script

General idea is to avoid actual calculation from property update()
callback and tag things for update later instead.

That said, pose constraint flags are now tagged for update and
handled as a part of object update. In the new depsgraph it'll
be a nice dedicated operation node.

Also avoid updating disabled flags for all the modifiers. This
part of the path is not totally optimal since it'll still need
to iterate over bones in order to get pchan, but to optimize it
further would be nice to find a way to avoid pchan requirement
all together.

Reviewers: campbellbarton

Reviewed By: campbellbarton

Differential Revision: https://developer.blender.org/D1191

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

M	source/blender/blenkernel/BKE_action.h
M	source/blender/blenkernel/intern/action.c
M	source/blender/blenkernel/intern/object.c
M	source/blender/editors/include/ED_object.h
M	source/blender/editors/object/object_constraint.c
M	source/blender/makesdna/DNA_action_types.h
M	source/blender/makesrna/intern/rna_constraint.c

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

diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 57ba6fd..f51e0fe 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -161,6 +161,9 @@ void extract_pose_from_pose(struct bPose *pose, const struct bPose *src);
 /* sets constraint flags */
 void BKE_pose_update_constraint_flags(struct bPose *pose);
 
+/* tag constraint flags for update */
+void BKE_pose_tag_update_constraint_flags(struct bPose *pose);
+
 /* return the name of structure pointed by pose->ikparam */
 const char *BKE_pose_ikparam_get_name(struct bPose *pose);
 
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index f9556bf..9ce198b 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -929,6 +929,12 @@ void BKE_pose_update_constraint_flags(bPose *pose)
 				pchan->constflag |= PCHAN_HAS_CONST;
 		}
 	}
+	pose->flag &= ~POSE_CONSTRAINTS_NEED_UPDATE_FLAGS;
+}
+
+void BKE_pose_tag_update_constraint_flags(bPose *pose)
+{
+	pose->flag |= POSE_CONSTRAINTS_NEED_UPDATE_FLAGS;
 }
 
 /* Clears all BONE_UNKEYED flags for every pose channel in every pose 
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index d63e251..08a74d0 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -3012,8 +3012,12 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx,
 {
 	if (ob->recalc & OB_RECALC_ALL) {
 		/* speed optimization for animation lookups */
-		if (ob->pose)
+		if (ob->pose) {
 			BKE_pose_channels_hash_make(ob->pose);
+			if (ob->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
+				BKE_pose_update_constraint_flags(ob->pose);
+			}
+		}
 
 		if (ob->recalc & OB_RECALC_DATA) {
 			if (ob->type == OB_ARMATURE) {
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 295bb75..3d79183 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -175,6 +175,9 @@ void ED_object_constraint_set_active(struct Object *ob, struct bConstraint *con)
 void ED_object_constraint_update(struct Object *ob);
 void ED_object_constraint_dependency_update(struct Main *bmain, struct Object *ob);
 
+void ED_object_constraint_tag_update(struct Object *ob, struct bConstraint *con);
+void ED_object_constraint_dependency_tag_update(struct Main *bmain, struct Object *ob, struct bConstraint *con);
+
 /* object_lattice.c */
 bool mouse_lattice(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
 void undo_push_lattice(struct bContext *C, const char *name);
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 231d23b..f1b349d 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -260,17 +260,221 @@ static void set_constraint_nth_target(bConstraint *con, Object *target, const ch
 
 /* ------------- Constraint Sanity Testing ------------------- */
 
-/* checks validity of object pointers, and NULLs,
- * if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag.
- */
-static void test_constraints(Object *owner, bPoseChannel *pchan)
+static void test_constraint(Object *owner, bPoseChannel *pchan, bConstraint *con, int type)
+{
+	bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+	ListBase targets = {NULL, NULL};
+	bConstraintTarget *ct;
+	bool check_targets = true;
+
+	/* clear disabled-flag first */
+	con->flag &= ~CONSTRAINT_DISABLE;
+
+	if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
+		bKinematicConstraint *data = con->data;
+
+		/* bad: we need a separate set of checks here as poletarget is
+		 *		optional... otherwise poletarget must exist too or else
+		 *		the constraint is deemed invalid
+		 */
+		/* default IK check ... */
+		if (BKE_object_exists_check(data->tar) == 0) {
+			data->tar = NULL;
+			con->flag |= CONSTRAINT_DISABLE;
+		}
+		else if (data->tar == owner) {
+			if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->subtarget)) {
+				con->flag |= CONSTRAINT_DISABLE;
+			}
+		}
+
+		if (data->poletar) {
+			if (BKE_object_exists_check(data->poletar) == 0) {
+				data->poletar = NULL;
+				con->flag |= CONSTRAINT_DISABLE;
+			}
+			else if (data->poletar == owner) {
+				if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->polesubtarget)) {
+					con->flag |= CONSTRAINT_DISABLE;
+				}
+			}
+		}
+		/* ... can be overwritten here */
+		BIK_test_constraint(owner, con);
+		/* targets have already been checked for this */
+		check_targets = false;
+	}
+	else if (con->type == CONSTRAINT_TYPE_PIVOT) {
+		bPivotConstraint *data = con->data;
+
+		/* target doesn't have to exist, but if it is non-null, it must exist! */
+		if (data->tar && BKE_object_exists_check(data->tar) == 0) {
+			data->tar = NULL;
+			con->flag |= CONSTRAINT_DISABLE;
+		}
+		else if (data->tar == owner) {
+			if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->subtarget)) {
+				con->flag |= CONSTRAINT_DISABLE;
+			}
+		}
+
+		/* targets have already been checked for this */
+		check_targets = false;
+	}
+	else if (con->type == CONSTRAINT_TYPE_ACTION) {
+		bActionConstraint *data = con->data;
+
+		/* validate action */
+		if (data->act == NULL) {
+			/* must have action */
+			con->flag |= CONSTRAINT_DISABLE;
+		}
+		else if (data->act->idroot != ID_OB) {
+			/* only object-rooted actions can be used */
+			data->act = NULL;
+			con->flag |= CONSTRAINT_DISABLE;
+		}
+	}
+	else if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) {
+		bFollowPathConstraint *data = con->data;
+
+		/* don't allow track/up axes to be the same */
+		if (data->upflag == data->trackflag)
+			con->flag |= CONSTRAINT_DISABLE;
+		if (data->upflag + 3 == data->trackflag)
+			con->flag |= CONSTRAINT_DISABLE;
+	}
+	else if (con->type == CONSTRAINT_TYPE_TRACKTO) {
+		bTrackToConstraint *data = con->data;
+
+		/* don't allow track/up axes to be the same */
+		if (data->reserved2 == data->reserved1)
+			con->flag |= CONSTRAINT_DISABLE;
+		if (data->reserved2 + 3 == data->reserved1)
+			con->flag |= CONSTRAINT_DISABLE;
+	}
+	else if (con->type == CONSTRAINT_TYPE_LOCKTRACK) {
+		bLockTrackConstraint *data = con->data;
+
+		if (data->lockflag == data->trackflag)
+			con->flag |= CONSTRAINT_DISABLE;
+		if (data->lockflag + 3 == data->trackflag)
+			con->flag |= CONSTRAINT_DISABLE;
+	}
+	else if (con->type == CONSTRAINT_TYPE_SPLINEIK) {
+		bSplineIKConstraint *data = con->data;
+
+		/* if the number of points does not match the amount required by the chain length,
+		 * free the points array and request a rebind...
+		 */
+		if ((data->points == NULL) || (data->numpoints != data->chainlen + 1)) {
+			/* free the points array */
+			if (data->points) {
+				MEM_freeN(data->points);
+				data->points = NULL;
+			}
+
+			/* clear the bound flag, forcing a rebind next time this is evaluated */
+			data->flag &= ~CONSTRAINT_SPLINEIK_BOUND;
+		}
+	}
+	else if (con->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
+		bFollowTrackConstraint *data = con->data;
+
+		if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0) {
+			if (data->clip != NULL && data->track[0]) {
+				MovieTracking *tracking = &data->clip->tracking;
+				MovieTrackingObject *tracking_object;
+
+				if (data->object[0])
+					tracking_object = BKE_tracking_object_get_named(tracking, data->object);
+				else
+					tracking_object = BKE_tracking_object_get_camera(tracking);
+
+				if (!tracking_object) {
+					con->flag |= CONSTRAINT_DISABLE;
+				}
+				else {
+					if (!BKE_tracking_track_get_named(tracking, tracking_object, data->track))
+						con->flag |= CONSTRAINT_DISABLE;
+				}
+			}
+			else {
+				con->flag |= CONSTRAINT_DISABLE;
+			}
+		}
+	}
+	else if (con->type == CONSTRAINT_TYPE_CAMERASOLVER) {
+		bCameraSolverConstraint *data = con->data;
+
+		if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL))
+			con->flag |= CONSTRAINT_DISABLE;
+	}
+	else if (con->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
+		bObjectSolverConstraint *data = con->data;
+
+		if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL))
+			con->flag |= CONSTRAINT_DISABLE;
+	}
+
+	/* Check targets for constraints */
+	if (check_targets && cti && cti->get_constraint_targets) {
+		cti->get_constraint_targets(con, &targets);
+
+		/* disable and clear constraints targets that are incorrect */
+		for (ct = targets.first; ct; ct = ct->next) {
+			/* general validity checks (for those constraints that need this) */
+			if (BKE_object_exists_check(ct->tar) == 0) {
+				/* object doesn't exist, but constraint requires target */
+				ct->tar = NULL;
+				con->flag |= CONSTRAINT_DISABLE;
+			}
+			else if (ct->tar == owner) {
+				if (type == CONSTRAINT_OBTYPE_BONE) {
+					if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), ct->subtarget)) {
+						/* bone must exist in armature... */
+						/* TODO: clear subtarget? */
+						con->flag |= CONSTRAINT_DISABLE;
+					}
+					else if (STREQ(pchan->name, ct->subtarget)) {
+						/* cannot target self */
+						ct->subtarget[0] = '\0';
+						con->flag |= CONSTRAINT_DISABLE;
+					}
+				}
+				else {
+					/* cannot use self as target */
+					ct->tar = NULL;
+					con->flag |= CONSTRAINT_DISABLE;
+				}
+			}
+
+			/* target checks for specific constraints */
+			if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) {
+				if (ct->tar) {
+					if (ct->tar->type != OB_CURVE) {
+						ct->tar = NULL;
+						con->flag |= CONSTRAINT_DISABLE;
+					}
+					else {
+						Curve *cu = ct->tar->data;
+
+						/* auto-set 'Path' setting on curve so this works  */
+						cu->flag |= CU_PATH;
+					}
+				}
+			}
+		}
+
+		/* free any temporary targets */
+		if (cti->flush_constraint_targets)
+			cti->flush_constraint_targets(con, &targets, 0);
+	}
+}
+
+static int constraint_type_get(Object *owner, bPoseChannel *pchan)
 {
-	bConstraint *curcon;
-	ListBase *conlist = NULL;
 	int type;
-	
-	if (owner == NULL) return;
-	
 	/* Ch

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list