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:
authorPhilipp Oeser <info@graphics-engineer.com>2019-07-05 16:50:48 +0300
committerPhilipp Oeser <info@graphics-engineer.com>2019-07-05 17:00:52 +0300
commit609e16339f13252a2dcaa2a5db4cf45c5e49e80b (patch)
tree818780e5ffd57420bae0d6d5d4be140e23c8d639 /source/blender/editors/object/object_constraint.c
parent34a0b65ba67e00a89522892bc6136df31658a051 (diff)
Fix "child of" constraint "set inverse" problematic with bones
For bone owners we want to do this in evaluated domain since BKE_pose_where_is() / BKE_pose_where_is_bone() rely on (re)evaluating parts of the scene and copying new evaluated stuff back to original. Fixes T66080, T66397 Reviewers: sergey Maniphest Tasks: T66080 Differential Revision: https://developer.blender.org/D5189
Diffstat (limited to 'source/blender/editors/object/object_constraint.c')
-rw-r--r--source/blender/editors/object/object_constraint.c167
1 files changed, 96 insertions, 71 deletions
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 53bc037c736..77b23081a62 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -53,6 +53,7 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
#ifdef WITH_PYTHON
# include "BPY_extern.h"
@@ -861,94 +862,106 @@ void CONSTRAINT_OT_limitdistance_reset(wmOperatorType *ot)
/* ------------- Child-Of Constraint ------------------ */
-static void child_get_inverse_matrix(const bContext *C,
- Scene *scene,
- Object *ob,
- bConstraint *con,
- float invmat[4][4],
- const int owner)
+static void child_get_inverse_matrix_owner_bone(
+ const bContext *C, wmOperator *op, Scene *scene, Object *ob, float invmat[4][4])
{
+ /* For bone owner we want to do this in evaluated domain.
+ * BKE_pose_where_is / BKE_pose_where_is_bone relies on (re)evaluating parts of the scene
+ * and copying new evaluated stuff back to original.
+ */
Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ bConstraint *con_eval = edit_constraint_property_get(op, ob_eval, CONSTRAINT_TYPE_CHILDOF);
/* nullify inverse matrix first */
unit_m4(invmat);
- if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
- bPoseChannel *pchan;
- /* try to find a pose channel - assume that this is the constraint owner */
- /* TODO: get from context instead? */
- if (ob && ob->pose && (pchan = BKE_pose_channel_active(ob))) {
- bConstraint *con_last;
- /* 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.
- */
- float imat[4][4], tmat[4][4];
- float pmat[4][4];
+ bPoseChannel *pchan_eval = BKE_pose_channel_active(ob_eval);
- /* make sure we passed the correct constraint */
- BLI_assert(BLI_findindex(&pchan->constraints, con) != -1);
+ /* try to find a pose channel - assume that this is the constraint owner */
+ /* TODO: get from context instead? */
+ if (ob_eval && ob_eval->pose && pchan_eval) {
+ bConstraint *con_last;
- /* 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
- */
- BKE_pose_where_is(depsgraph, scene, ob);
- copy_m4_m4(pmat, pchan->pose_mat);
+ /* 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.
+ */
+ float imat[4][4], tmat[4][4];
+ float pmat[4][4];
- /* 2. knock out constraints starting from this one */
- con_last = pchan->constraints.last;
- pchan->constraints.last = con->prev;
+ /* make sure we passed the correct constraint */
+ BLI_assert(BLI_findindex(&pchan_eval->constraints, con_eval) != -1);
- 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;
- }
+ /* 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
+ */
+ BKE_pose_where_is(depsgraph, scene, ob_eval);
+ copy_m4_m4(pmat, pchan_eval->pose_mat);
- /* 3. solve pose without disabled constraints */
- BKE_pose_where_is(depsgraph, scene, ob);
+ /* 2. knock out constraints starting from this one */
+ con_last = pchan_eval->constraints.last;
+ pchan_eval->constraints.last = con_eval->prev;
- /* 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
- */
- invert_m4_m4(imat, pchan->pose_mat);
- mul_m4_m4m4(tmat, pmat, imat);
- invert_m4_m4(invmat, tmat);
+ if (con_eval->prev) {
+ /* new end must not point to this one, else this chain cutting is useless */
+ con_eval->prev->next = NULL;
+ }
+ else {
+ /* constraint was first */
+ pchan_eval->constraints.first = NULL;
+ }
- /* 5. restore constraints */
- pchan->constraints.last = con_last;
+ /* 3. solve pose without disabled constraints */
+ BKE_pose_where_is(depsgraph, scene, ob_eval);
- if (con->prev) {
- /* hook up prev to this one again */
- con->prev->next = con;
- }
- else {
- /* set as first again */
- pchan->constraints.first = con;
- }
+ /* 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
+ */
+ invert_m4_m4(imat, pchan_eval->pose_mat);
+ mul_m4_m4m4(tmat, pmat, imat);
+ invert_m4_m4(invmat, tmat);
+
+ /* 5. restore constraints */
+ pchan_eval->constraints.last = con_last;
- /* 6. recalculate pose with new inv-mat applied */
- BKE_pose_where_is(depsgraph, scene, ob);
+ if (con_eval->prev) {
+ /* hook up prev to this one again */
+ con_eval->prev->next = con_eval;
}
+ else {
+ /* set as first again */
+ pchan_eval->constraints.first = con_eval;
+ }
+
+ /* 6. recalculate pose with new inv-mat applied */
+ /* this one is unnecessary? (DEG seems to update correctly without)
+ + if we leave this in, we have to click "Set Inverse" twice to see updates...
+ BKE_pose_where_is(depsgraph, scene, ob_eval); */
}
- if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
- if (ob) {
- Object workob;
+}
- /* make sure we passed the correct constraint */
- BLI_assert(BLI_findindex(&ob->constraints, con) != -1);
+static void child_get_inverse_matrix_owner_object(
+ const bContext *C, Scene *scene, Object *ob, bConstraint *con, float invmat[4][4])
+{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
- /* use BKE_object_workob_calc_parent to find inverse - just like for normal parenting */
- BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(invmat, workob.obmat);
- }
+ /* nullify inverse matrix first */
+ unit_m4(invmat);
+
+ if (ob) {
+ Object workob;
+
+ /* make sure we passed the correct constraint */
+ BLI_assert(BLI_findindex(&ob->constraints, con) != -1);
+
+ /* use BKE_object_workob_calc_parent to find inverse - just like for normal parenting */
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
+ invert_m4_m4(invmat, workob.obmat);
}
}
@@ -969,7 +982,12 @@ static int childof_set_inverse_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- child_get_inverse_matrix(C, scene, ob, con, data->invmat, owner);
+ if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
+ child_get_inverse_matrix_owner_object(C, scene, ob, con, data->invmat);
+ }
+ else if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
+ child_get_inverse_matrix_owner_bone(C, op, scene, ob, data->invmat);
+ }
ED_object_constraint_update(bmain, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
@@ -1203,6 +1221,7 @@ void CONSTRAINT_OT_followpath_path_animate(wmOperatorType *ot)
static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
@@ -1216,8 +1235,14 @@ static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- child_get_inverse_matrix(C, scene, ob, con, data->invmat, owner);
+ if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
+ child_get_inverse_matrix_owner_object(C, scene, ob, con, data->invmat);
+ }
+ else if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
+ child_get_inverse_matrix_owner_bone(C, op, scene, ob, data->invmat);
+ }
+ ED_object_constraint_update(bmain, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
return OPERATOR_FINISHED;