diff options
Diffstat (limited to 'source/blender/blenkernel/intern/constraint.c')
-rw-r--r-- | source/blender/blenkernel/intern/constraint.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 0da29ded13d..4b26022039e 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -5677,6 +5677,111 @@ bool BKE_constraint_remove_ex(ListBase *list, Object *ob, bConstraint *con, bool return false; } +/* Apply the specified constraint in the given constraint stack */ +bool BKE_constraint_apply_for_object(Depsgraph *depsgraph, + Scene *scene, + Object *ob, + bConstraint *con) +{ + if (!con) { + return false; + } + + const float ctime = BKE_scene_frame_get(scene); + + bConstraint *new_con = BKE_constraint_duplicate_ex(con, 0, !ID_IS_LINKED(ob)); + ListBase single_con = {new_con, new_con}; + + bConstraintOb *cob = BKE_constraints_make_evalob( + depsgraph, scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); + /* Undo the effect of the current constraint stack evaluation. */ + mul_m4_m4m4(cob->matrix, ob->constinv, cob->matrix); + + /* Evaluate single constraint. */ + BKE_constraints_solve(depsgraph, &single_con, cob, ctime); + /* Copy transforms back. This will leave the object in a bad state + * as ob->constinv will be wrong until next evaluation. */ + BKE_constraints_clear_evalob(cob); + + /* Free the copied constraint. */ + BKE_constraint_free_data(new_con); + BLI_freelinkN(&single_con, new_con); + + /* Apply transform from matrix. */ + BKE_object_apply_mat4(ob, ob->obmat, true, true); + + return true; +} + +bool BKE_constraint_apply_and_remove_for_object(Depsgraph *depsgraph, + Scene *scene, + ListBase /*bConstraint*/ *constraints, + Object *ob, + bConstraint *con) +{ + if (!BKE_constraint_apply_for_object(depsgraph, scene, ob, con)) { + return false; + } + + return BKE_constraint_remove_ex(constraints, ob, con, true); +} + +bool BKE_constraint_apply_for_pose( + Depsgraph *depsgraph, Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con) +{ + if (!con) { + return false; + } + + const float ctime = BKE_scene_frame_get(scene); + + bConstraint *new_con = BKE_constraint_duplicate_ex(con, 0, !ID_IS_LINKED(ob)); + ListBase single_con; + single_con.first = new_con; + single_con.last = new_con; + + float vec[3]; + copy_v3_v3(vec, pchan->pose_mat[3]); + + bConstraintOb *cob = BKE_constraints_make_evalob( + depsgraph, scene, ob, pchan, CONSTRAINT_OBTYPE_BONE); + /* Undo the effects of currently applied constraints. */ + mul_m4_m4m4(cob->matrix, pchan->constinv, cob->matrix); + /* Evaluate single constraint. */ + BKE_constraints_solve(depsgraph, &single_con, cob, ctime); + BKE_constraints_clear_evalob(cob); + + /* Free the copied constraint. */ + BKE_constraint_free_data(new_con); + BLI_freelinkN(&single_con, new_con); + + /* Prevent constraints breaking a chain. */ + if (pchan->bone->flag & BONE_CONNECTED) { + copy_v3_v3(pchan->pose_mat[3], vec); + } + + /* Apply transform from matrix. */ + float mat[4][4]; + BKE_armature_mat_pose_to_bone(pchan, pchan->pose_mat, mat); + BKE_pchan_apply_mat4(pchan, mat, true); + + return true; +} + +bool BKE_constraint_apply_and_remove_for_pose(Depsgraph *depsgraph, + Scene *scene, + ListBase /*bConstraint*/ *constraints, + Object *ob, + bConstraint *con, + bPoseChannel *pchan) +{ + if (!BKE_constraint_apply_for_pose(depsgraph, scene, ob, pchan, con)) { + return false; + } + + return BKE_constraint_remove_ex(constraints, ob, con, true); +} + void BKE_constraint_panel_expand(bConstraint *con) { con->ui_expand_flag |= UI_PANEL_DATA_EXPAND_ROOT; |