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:
authorSybren A. Stüvel <sybren@blender.org>2020-09-01 18:57:42 +0300
committerSybren A. Stüvel <sybren@blender.org>2020-09-01 18:57:42 +0300
commita92ab93c7dc3f54ffd8290dd8055998a2c932998 (patch)
treed10f7711c90c0114849008ba9e5818a6a638bce3
parent23767937ef6bd61736dae09da0fff0a69b37aa5b (diff)
Fix T79553: StretchTo constraint: Apply Pose changes bone length
Recompute Rest Length stored in the StretchTo constraint after applying the current pose as rest pose. The "Apply Pose as Rest Pose" operator applies the evaluated pose as rest pose, which means that the change in bone length from the StretchTo constraint is applied to the rest pose. The bug was caused by the fact that the StretchTo constraint wasn't updated for the new pose, and thus still applied the same scale factor to the new pose, effectively doubling its effect. The "Apply Pose as Rest Pose" operator now forces a recompute of the rest length cached in the StretchTo constraint data. As a result, the length of the bone before and after the pose is applied remains the same. The X and Z scale (perpendicular to the bone length) are reset to 1.0, as with the applied pose the bone isn't stretched or squashed any more.
-rw-r--r--source/blender/editors/armature/pose_transform.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c
index a6cf8552ca4..b09015096a6 100644
--- a/source/blender/editors/armature/pose_transform.c
+++ b/source/blender/editors/armature/pose_transform.c
@@ -23,6 +23,7 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -338,6 +339,46 @@ static void applyarmature_process_selected_recursive(bArmature *arm,
}
}
+/* Reset bone constraint so that it is correct after the pose has been applied. */
+static void applyarmature_reset_bone_constraint(const bConstraint *constraint)
+{
+ /* TODO(Sybren): This function needs too much knowledge of the internals of specific constraints.
+ * When it is extended with one or two more constraints, move the functionality into a
+ * bConstraintTypeInfo callback function. */
+ switch (constraint->type) {
+ case CONSTRAINT_TYPE_STRETCHTO: {
+ bStretchToConstraint *stretch_to = (bStretchToConstraint *)constraint->data;
+ stretch_to->orglength = 0.0f; /* Force recalculation on next evaluation. */
+ break;
+ }
+ default:
+ /* Most constraints don't need resetting. */
+ break;
+ }
+}
+
+/* Reset bone constraints of the given pose channel so that they are correct after the pose has
+ * been applied. */
+static void applyarmature_reset_bone_constraints(const bPoseChannel *pchan)
+{
+ LISTBASE_FOREACH (bConstraint *, constraint, &pchan->constraints) {
+ applyarmature_reset_bone_constraint(constraint);
+ }
+}
+
+/* Reset all (or only selected) bone constraints so that they are correct after the pose has been
+ * applied. */
+static void applyarmature_reset_constraints(bPose *pose, const bool use_selected)
+{
+ for (bPoseChannel *pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
+ BLI_assert(pchan->bone != NULL);
+ if (use_selected && (pchan->bone->flag & BONE_SELECTED) == 0) {
+ continue;
+ }
+ applyarmature_reset_bone_constraints(pchan);
+ }
+}
+
/* set the current pose as the restpose */
static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
{
@@ -416,6 +457,9 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
/* fix parenting of objects which are bone-parented */
applyarmature_fix_boneparents(C, scene, ob);
+ /* For the affected bones, reset specific constraints that are now known to be invalid. */
+ applyarmature_reset_constraints(pose, use_selected);
+
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);