Fix T67507: Set origin on armature moves incorrectly parented objects
authorSergey Sharybin <sergey.vfx@gmail.com>
Wed, 24 Jul 2019 08:08:42 +0000 (10:08 +0200)
committerSergey Sharybin <sergey.vfx@gmail.com>
Fri, 26 Jul 2019 08:15:39 +0000 (10:15 +0200)
Need to copy changes from original armature to evaluated one prior to
BKE_pose_where_is(), otherwise the pose matrix in pose channels will
not be correct.

Can not use dependency graph update here, since we must not re-evaluate
possible dependencies of the changed armature.

Reviewers: brecht

Reviewed By: brecht

Maniphest Tasks: T67507

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

source/blender/blenkernel/BKE_armature.h
source/blender/blenkernel/intern/armature.c
source/blender/editors/object/object_transform.c

index 73e62f6a7b3464b0d39d3e91677ee12c039e5abf..99c6bb405b5e3b70436020b12b2d0215e7c7af3c 100644 (file)
@@ -75,6 +75,9 @@ void BKE_armature_copy_data(struct Main *bmain,
                             const int flag);
 struct bArmature *BKE_armature_copy(struct Main *bmain, const struct bArmature *arm);
 
+void BKE_armature_copy_bone_transforms(struct bArmature *armature_dst,
+                                       const struct bArmature *armature_src);
+
 /* Bounding box. */
 struct BoundBox *BKE_armature_boundbox_get(struct Object *ob);
 
index c36acd1eae1b2a330313a7384e689778ff6f407f..3621926e93b366f80efb50e3e421ece4fc80ee0b 100644 (file)
@@ -239,6 +239,35 @@ bArmature *BKE_armature_copy(Main *bmain, const bArmature *arm)
   return arm_copy;
 }
 
+static void copy_bone_transform(Bone *bone_dst, const Bone *bone_src)
+{
+  bone_dst->roll = bone_src->roll;
+
+  copy_v3_v3(bone_dst->head, bone_src->head);
+  copy_v3_v3(bone_dst->tail, bone_src->tail);
+
+  copy_m3_m3(bone_dst->bone_mat, bone_src->bone_mat);
+
+  copy_v3_v3(bone_dst->arm_head, bone_src->arm_head);
+  copy_v3_v3(bone_dst->arm_tail, bone_src->arm_tail);
+
+  copy_m4_m4(bone_dst->arm_mat, bone_src->arm_mat);
+
+  bone_dst->arm_roll = bone_src->arm_roll;
+}
+
+void BKE_armature_copy_bone_transforms(bArmature *armature_dst, const bArmature *armature_src)
+{
+  Bone *bone_dst = armature_dst->bonebase.first;
+  const Bone *bone_src = armature_src->bonebase.first;
+  while (bone_dst != NULL) {
+    BLI_assert(bone_src != NULL);
+    copy_bone_transform(bone_dst, bone_src);
+    bone_dst = bone_dst->next;
+    bone_src = bone_src->next;
+  }
+}
+
 static Bone *get_named_bone_bonechildren(ListBase *lb, const char *name)
 {
   Bone *curBone, *rbone;
index 9c98fdc2a2e0f980497af581d873ee9122b5db94..3f7d5dba149ff9bffda626bbef198a012a248c35 100644 (file)
@@ -856,6 +856,7 @@ static int apply_objects_internal(bContext *C,
     BKE_object_where_is_calc(depsgraph, scene, ob_eval);
     if (ob->type == OB_ARMATURE) {
       /* needed for bone parents */
+      BKE_armature_copy_bone_transforms(ob_eval->data, ob->data);
       BKE_pose_where_is(depsgraph, scene, ob_eval);
     }
 
@@ -1229,6 +1230,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
 
           Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
           BKE_object_transform_copy(ob_eval, ob);
+          BKE_armature_copy_bone_transforms(ob_eval->data, ob->data);
           BKE_object_where_is_calc(depsgraph, scene, ob_eval);
           BKE_pose_where_is(depsgraph, scene, ob_eval); /* needed for bone parents */
 
@@ -1370,6 +1372,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
         BKE_object_where_is_calc(depsgraph, scene, ob_eval);
         if (ob->type == OB_ARMATURE) {
           /* needed for bone parents */
+          BKE_armature_copy_bone_transforms(ob_eval->data, ob->data);
           BKE_pose_where_is(depsgraph, scene, ob_eval);
         }
 
@@ -1398,6 +1401,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
             BKE_object_where_is_calc(depsgraph, scene, ob_other_eval);
             if (ob_other->type == OB_ARMATURE) {
               /* needed for bone parents */
+              BKE_armature_copy_bone_transforms(ob_eval->data, ob->data);
               BKE_pose_where_is(depsgraph, scene, ob_other_eval);
             }
             ignore_parent_tx(bmain, depsgraph, scene, ob_other);