Copy Scale: support copying arbitrary non-uniform scale as uniform.
authorAlexander Gavrilov <angavrilov@gmail.com>
Wed, 28 Aug 2019 13:56:27 +0000 (16:56 +0300)
committerAlexander Gavrilov <angavrilov@gmail.com>
Thu, 29 Aug 2019 14:22:27 +0000 (17:22 +0300)
Uniform scale is superior to non-uniform scale in that it works with
parenting without causing shear. Thus it is a valid desire in some
cases to turn arbitrary scale into guaranteed uniform scale.

Implementing this in the Copy Scale constraint allows one for instance
to 'inherit scale as uniform' by disabling Inherit Scale, and using
Copy Scale from parent with Offset and Make Uniform.

Reviewers: brecht

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

release/scripts/startup/bl_ui/properties_constraint.py
source/blender/blenkernel/intern/constraint.c
source/blender/makesdna/DNA_constraint_types.h
source/blender/makesrna/intern/rna_constraint.c

index 6fa953574cbe4187d742ec30c8c70bb0f0beb636..d8eb0db62fce2a9074acbab23c959be3b5f8b2f4 100644 (file)
@@ -430,6 +430,7 @@ class ConstraintButtonsPanel:
         row.prop(con, "use_z", text="Z")
 
         layout.prop(con, "power")
+        layout.prop(con, "use_make_uniform")
 
         row = layout.row()
         row.prop(con, "use_offset")
index e1e4d138fd909375a4d13211c7a2358933c6aee0..1a3c562941e167e99afc50d7d8fd09f8220257c3 100644 (file)
@@ -1927,9 +1927,39 @@ static void sizelike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *ta
   if (VALID_CONS_TARGET(ct)) {
     float obsize[3], size[3];
 
-    mat4_to_size(size, ct->matrix);
     mat4_to_size(obsize, cob->matrix);
 
+    /* Compute one uniform scale factor to apply to all three axes. */
+    if (data->flag & SIZELIKE_UNIFORM) {
+      const int all_axes = SIZELIKE_X | SIZELIKE_Y | SIZELIKE_Z;
+      float total = 1.0f;
+
+      /* If all axes are selected, use the determinant. */
+      if ((data->flag & all_axes) == all_axes) {
+        total = fabsf(mat4_to_volume_scale(ct->matrix));
+      }
+      /* Otherwise multiply individual values. */
+      else {
+        mat4_to_size(size, ct->matrix);
+
+        if (data->flag & SIZELIKE_X) {
+          total *= size[0];
+        }
+        if (data->flag & SIZELIKE_Y) {
+          total *= size[1];
+        }
+        if (data->flag & SIZELIKE_Z) {
+          total *= size[2];
+        }
+      }
+
+      copy_v3_fl(size, cbrt(total));
+    }
+    /* Regular per-axis scaling. */
+    else {
+      mat4_to_size(size, ct->matrix);
+    }
+
     for (int i = 0; i < 3; i++) {
       size[i] = powf(size[i], data->power);
     }
@@ -1948,13 +1978,13 @@ static void sizelike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *ta
       }
     }
 
-    if ((data->flag & SIZELIKE_X) && (obsize[0] != 0)) {
+    if ((data->flag & (SIZELIKE_X | SIZELIKE_UNIFORM)) && (obsize[0] != 0)) {
       mul_v3_fl(cob->matrix[0], size[0] / obsize[0]);
     }
-    if ((data->flag & SIZELIKE_Y) && (obsize[1] != 0)) {
+    if ((data->flag & (SIZELIKE_Y | SIZELIKE_UNIFORM)) && (obsize[1] != 0)) {
       mul_v3_fl(cob->matrix[1], size[1] / obsize[1]);
     }
-    if ((data->flag & SIZELIKE_Z) && (obsize[2] != 0)) {
+    if ((data->flag & (SIZELIKE_Z | SIZELIKE_UNIFORM)) && (obsize[2] != 0)) {
       mul_v3_fl(cob->matrix[2], size[2] / obsize[2]);
     }
   }
index eda52fdf14a752b10133dcb50097a468c6c1c0c4..17ce279f1b763d603a41cb32f0e3732d9be06754 100644 (file)
@@ -748,6 +748,7 @@ typedef enum eCopyScale_Flags {
   SIZELIKE_Z = (1 << 2),
   SIZELIKE_OFFSET = (1 << 3),
   SIZELIKE_MULTIPLY = (1 << 4),
+  SIZELIKE_UNIFORM = (1 << 5),
 } eCopyScale_Flags;
 
 /* bTransformConstraint.to/from */
index 08d2a03b2a96d0f9053f7542abb77740e434bf7d..539e2a6629643381208430397285c7369e99562d 100644 (file)
@@ -1364,6 +1364,14 @@ static void rna_def_constraint_size_like(BlenderRNA *brna)
   RNA_def_property_ui_text(prop, "Power", "Raise the target's scale to the specified power");
   RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
 
+  prop = RNA_def_property(srna, "use_make_uniform", PROP_BOOLEAN, PROP_NONE);
+  RNA_def_property_boolean_sdna(prop, NULL, "flag", SIZELIKE_UNIFORM);
+  RNA_def_property_ui_text(prop,
+                           "Make Uniform",
+                           "Redistribute the copied change in volume equally "
+                           "between the three axes of the owner");
+  RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
   prop = RNA_def_property(srna, "use_offset", PROP_BOOLEAN, PROP_NONE);
   RNA_def_property_boolean_sdna(prop, NULL, "flag", SIZELIKE_OFFSET);
   RNA_def_property_ui_text(prop, "Offset", "Combine original scale with copied scale");