Fix T65671: Armature X-Mirror inconsistencies
authorDemeter Dzadik <Mets>
Wed, 21 Aug 2019 07:59:11 +0000 (09:59 +0200)
committerSebastian Parborg <darkdefende@gmail.com>
Wed, 21 Aug 2019 07:59:11 +0000 (09:59 +0200)
This fixes bendy bone properties not being mirrored correctly

Reviewed By: Brecht

Differential Revision: http://developer.blender.org/D5408

source/blender/editors/armature/armature_utils.c
source/blender/editors/include/ED_armature.h
source/blender/editors/transform/transform.h
source/blender/editors/transform/transform_conversions.c
source/blender/makesrna/intern/rna_armature.c

index d8777b7e0b73e100aa4dc6e7f52a9574e9d1add4..63b55a3f1b834baad3efce15febb6db8f54d03a4 100644 (file)
@@ -381,23 +381,33 @@ void armature_tag_unselect(bArmature *arm)
 
 void ED_armature_ebone_transform_mirror_update(bArmature *arm, EditBone *ebo, bool check_select)
 {
+  /* TODO When this function is called by property updates, cancelling the value change will not restore mirrored bone correctly. */
+  /* Currently check_select==true when this function is called from a transform operator, eg. from 3d viewport. */
   /* no layer check, correct mirror is more important */
   if (!check_select || ebo->flag & (BONE_TIPSEL | BONE_ROOTSEL)) {
     EditBone *eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
     if (eboflip) {
-      /* we assume X-axis flipping for now */
-      if (check_select && ebo->flag & BONE_TIPSEL) {
-        EditBone *children;
+      /* We assume X-axis flipping for now. */
+
+      /* Always mirror roll, since it can be changed by moving either head or tail. */
+      eboflip->roll = -ebo->roll;
+
+      if (!check_select || ebo->flag & BONE_TIPSEL) {
+        /* Mirror tail properties. */
 
         eboflip->tail[0] = -ebo->tail[0];
         eboflip->tail[1] = ebo->tail[1];
         eboflip->tail[2] = ebo->tail[2];
         eboflip->rad_tail = ebo->rad_tail;
-        eboflip->roll = -ebo->roll;
         eboflip->curve_out_x = -ebo->curve_out_x;
+        eboflip->curve_out_y = ebo->curve_out_y;
+        eboflip->scale_out_x = ebo->scale_out_x;
+        eboflip->scale_out_y = ebo->scale_out_y;
+        eboflip->ease2 = ebo->ease2;
         eboflip->roll2 = -ebo->roll2;
 
-        /* Also move connected children, in case children's name aren't mirrored properly */
+        /* Also move connected children, in case children's name aren't mirrored properly. */
+        EditBone *children;
         for (children = arm->edbo->first; children; children = children->next) {
           if (children->parent == eboflip && children->flag & BONE_CONNECTED) {
             copy_v3_v3(children->head, eboflip->tail);
@@ -405,32 +415,38 @@ void ED_armature_ebone_transform_mirror_update(bArmature *arm, EditBone *ebo, bo
           }
         }
       }
+
       if (!check_select || ebo->flag & BONE_ROOTSEL) {
+        /* Mirror head properties. */
         eboflip->head[0] = -ebo->head[0];
         eboflip->head[1] = ebo->head[1];
         eboflip->head[2] = ebo->head[2];
         eboflip->rad_head = ebo->rad_head;
-        eboflip->roll = -ebo->roll;
+
         eboflip->curve_in_x = -ebo->curve_in_x;
+        eboflip->curve_in_y = ebo->curve_in_y;
+        eboflip->scale_in_x = ebo->scale_in_x;
+        eboflip->scale_in_y = ebo->scale_in_y;
+        eboflip->ease1 = ebo->ease1;
         eboflip->roll1 = -ebo->roll1;
 
-        /* Also move connected parent, in case parent's name isn't mirrored properly */
+        /* Also move connected parent, in case parent's name isn't mirrored properly. */
         if (eboflip->parent && eboflip->flag & BONE_CONNECTED) {
           EditBone *parent = eboflip->parent;
           copy_v3_v3(parent->tail, eboflip->head);
           parent->rad_tail = ebo->rad_head;
         }
       }
+
       if (!check_select || ebo->flag & BONE_SELECTED) {
+        /* Mirror bone body properties (both head and tail are selected). */
+        /* TODO: These values can also be changed from pose mode, so only mirroring them in edit mode is not ideal. */
         eboflip->dist = ebo->dist;
-        eboflip->roll = -ebo->roll;
+        eboflip->weight = ebo->weight;
+
+        eboflip->segments = ebo->segments;
         eboflip->xwidth = ebo->xwidth;
         eboflip->zwidth = ebo->zwidth;
-
-        eboflip->curve_in_x = -ebo->curve_in_x;
-        eboflip->curve_out_x = -ebo->curve_out_x;
-        eboflip->roll1 = -ebo->roll1;
-        eboflip->roll2 = -ebo->roll2;
       }
     }
   }
index 6629eed8328167ef3b17ef4e7f7f70c4d023fa28..76be0e82aa43d5108c6e86bce5cee9cd21e6d32c 100644 (file)
@@ -75,12 +75,14 @@ typedef struct EditBone {
   int flag;
   int layer;
 
+  /* Envelope distance & weight */
   float dist, weight;
   /** put them in order! transform uses this as scale */
   float xwidth, length, zwidth;
   float rad_head, rad_tail;
 
   /* Bendy-Bone parameters */
+  short segments;
   float roll1, roll2;
   float curve_in_x, curve_in_y;
   float curve_out_x, curve_out_y;
@@ -91,8 +93,6 @@ typedef struct EditBone {
   /** for envelope scaling */
   float oldlength;
 
-  short segments;
-
   /** Type of next/prev bone handles */
   char bbone_prev_type;
   char bbone_next_type;
index b023199fa1bd5db28aebdbff128356202fb6d39e..a2195c978238b27b2247243d62e4290d85e80e15 100644 (file)
@@ -375,6 +375,7 @@ typedef struct VertSlideParams {
 typedef struct BoneInitData {
   struct EditBone *bone;
   float tail[3];
+  float rad_head;
   float rad_tail;
   float roll;
   float head[3];
index 2fb9e2b95913b47c17aaa1d802b6ca96c6526b43..2684b6e279d495d50c5316b708406f0968076c60 100644 (file)
@@ -1517,6 +1517,7 @@ void restoreBones(TransDataContainer *tc)
     ebo = bid->bone;
 
     ebo->dist = bid->dist;
+    ebo->rad_head = bid->rad_head;
     ebo->rad_tail = bid->rad_tail;
     ebo->roll = bid->roll;
     ebo->xwidth = bid->xwidth;
@@ -1782,6 +1783,7 @@ static void createTransArmatureVerts(TransInfo *t)
         if (eboflip) {
           bid[i].bone = eboflip;
           bid[i].dist = eboflip->dist;
+          bid[i].rad_head = eboflip->rad_head;
           bid[i].rad_tail = eboflip->rad_tail;
           bid[i].roll = eboflip->roll;
           bid[i].xwidth = eboflip->xwidth;
index 59e5c5848119dfcc9a871a6f83e24ef9926234f7..bc6d3b6e743b2104e3b88c0c58fb4ebdb5b58016 100644 (file)
@@ -621,7 +621,7 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone)
         RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); \
       } \
       else { \
-        RNA_def_property_update(prop, 0, "rna_Armature_update_data"); \
+        RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update"); \
       } \
     } \
     ((void)0)
@@ -871,11 +871,16 @@ static void rna_def_bone_common(StructRNA *srna, int editbone)
   /* Number values */
   /* envelope deform settings */
   prop = RNA_def_property(srna, "envelope_distance", PROP_FLOAT, PROP_DISTANCE);
+  if (editbone) {
+    RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update");
+  }
+  else {
+    RNA_def_property_update(prop, 0, "rna_Armature_update_data");
+  }
   RNA_def_property_float_sdna(prop, NULL, "dist");
   RNA_def_property_range(prop, 0.0f, 1000.0f);
   RNA_def_property_ui_text(
       prop, "Envelope Deform Distance", "Bone deformation distance (for Envelope deform only)");
-  RNA_def_property_update(prop, 0, "rna_Armature_update_data");
 
   prop = RNA_def_property(srna, "envelope_weight", PROP_FLOAT, PROP_NONE);
   RNA_def_property_float_sdna(prop, NULL, "weight");
@@ -914,23 +919,38 @@ static void rna_def_bone_common(StructRNA *srna, int editbone)
 
   /* b-bones deform settings */
   prop = RNA_def_property(srna, "bbone_segments", PROP_INT, PROP_NONE);
+  if (editbone) {
+    RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update");
+  }
+  else {
+    RNA_def_property_update(prop, 0, "rna_Armature_dependency_update");
+  }
   RNA_def_property_int_sdna(prop, NULL, "segments");
   RNA_def_property_range(prop, 1, 32);
   RNA_def_property_ui_text(
       prop, "B-Bone Segments", "Number of subdivisions of bone (for B-Bones only)");
-  RNA_def_property_update(prop, 0, "rna_Armature_dependency_update");
 
   prop = RNA_def_property(srna, "bbone_x", PROP_FLOAT, PROP_NONE);
+  if (editbone) {
+    RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update");
+  }
+  else {
+    RNA_def_property_update(prop, 0, "rna_Armature_update_data");
+  }
   RNA_def_property_float_sdna(prop, NULL, "xwidth");
   RNA_def_property_ui_range(prop, 0.0f, 1000.0f, 1, RNA_TRANSLATION_PREC_DEFAULT);
   RNA_def_property_ui_text(prop, "B-Bone Display X Width", "B-Bone X size");
-  RNA_def_property_update(prop, 0, "rna_Armature_update_data");
 
   prop = RNA_def_property(srna, "bbone_z", PROP_FLOAT, PROP_NONE);
+  if (editbone) {
+    RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update");
+  }
+  else {
+    RNA_def_property_update(prop, 0, "rna_Armature_update_data");
+  }
   RNA_def_property_float_sdna(prop, NULL, "zwidth");
   RNA_def_property_ui_range(prop, 0.0f, 1000.0f, 1, RNA_TRANSLATION_PREC_DEFAULT);
   RNA_def_property_ui_text(prop, "B-Bone Display Z Width", "B-Bone Z size");
-  RNA_def_property_update(prop, 0, "rna_Armature_update_data");
 
   prop = RNA_def_property(srna, "bbone_handle_type_start", PROP_ENUM, PROP_NONE);
   RNA_def_property_enum_sdna(prop, NULL, "bbone_prev_type");