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:
-rw-r--r--source/blender/editors/object/object_constraint.c52
1 files changed, 41 insertions, 11 deletions
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 3c84b2df1d2..40d52e0b261 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -691,6 +691,7 @@ static int childof_set_inverse_exec (bContext *C, wmOperator *op)
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF);
bChildOfConstraint *data= (con) ? (bChildOfConstraint *)con->data : NULL;
+ bConstraint *lastcon = NULL;
bPoseChannel *pchan= NULL;
/* despite 3 layers of checks, we may still not be able to find a constraint */
@@ -703,27 +704,45 @@ static int childof_set_inverse_exec (bContext *C, wmOperator *op)
/* nullify inverse matrix first */
unit_m4(data->invmat);
- /* try to find a pose channel */
+ /* try to find a pose channel - assume that this is the constraint owner */
// TODO: get from context instead?
if (ob && ob->pose)
pchan= get_active_posechannel(ob);
- /* calculate/set inverse matrix */
+ /* calculate/set inverse matrix:
+ * We just calculate all transform-stack eval up to but not including this constraint.
+ * This is because inverse should just inverse correct for just the constraint's influence
+ * when it gets applied; that is, at the time of application, we don't know anything about
+ * what follows.
+ */
if (pchan) {
- float pmat[4][4], cinf;
float imat[4][4], tmat[4][4];
+ float pmat[4][4];
- /* make copy of pchan's original pose-mat (for use later) */
+ /* 1. calculate posemat where inverse doesn't exist yet (inverse was cleared above),
+ * to use as baseline ("pmat") to derive delta from. This extra calc saves users
+ * from having pressing "Clear Inverse" first
+ */
+ where_is_pose(scene, ob);
copy_m4_m4(pmat, pchan->pose_mat);
- /* disable constraint for pose to be solved without it */
- cinf= con->enforce;
- con->enforce= 0.0f;
+ /* 2. knock out constraints starting from this one */
+ lastcon = pchan->constraints.last;
+ pchan->constraints.last = con->prev;
+
+ if (con->prev) {
+ /* new end must not point to this one, else this chain cutting is useless */
+ con->prev->next = NULL;
+ }
+ else {
+ /* constraint was first */
+ pchan->constraints.first = NULL;
+ }
- /* solve pose without constraint */
+ /* 3. solve pose without disabled constraints */
where_is_pose(scene, ob);
- /* determine effect of constraint by removing the newly calculated
+ /* 4. determine effect of constraint by removing the newly calculated
* pchan->pose_mat from the original pchan->pose_mat, thus determining
* the effect of the constraint
*/
@@ -731,8 +750,19 @@ static int childof_set_inverse_exec (bContext *C, wmOperator *op)
mul_m4_m4m4(tmat, imat, pmat);
invert_m4_m4(data->invmat, tmat);
- /* recalculate pose with new inv-mat */
- con->enforce= cinf;
+ /* 5. restore constraints */
+ pchan->constraints.last = lastcon;
+
+ if (con->prev) {
+ /* hook up prev to this one again */
+ con->prev->next = con;
+ }
+ else {
+ /* set as first again */
+ pchan->constraints.first = con;
+ }
+
+ /* 6. recalculate pose with new inv-mat applied */
where_is_pose(scene, ob);
}
else if (ob) {